[exim-cvs] common driver structs for transports

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Exim Git Commits Mailing List
Ημερομηνία:  
Προς: exim-cvs
Αντικείμενο: [exim-cvs] common driver structs for transports
Gitweb: https://git.exim.org/exim.git/commitdiff/1c3dfdb67cc4aabc21db9fcc5a118e7ad82b44ab
Commit:     1c3dfdb67cc4aabc21db9fcc5a118e7ad82b44ab
Parent:     479274b860536bee4e54636557959389f71ad31b
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sat Aug 10 00:13:47 2024 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sat Aug 10 21:49:33 2024 +0100


    common driver structs for transports
---
 src/src/deliver.c                  | 201 ++++++++++++++++++++-----------------
 src/src/dns.c                      |   4 +-
 src/src/drtables.c                 |  84 +++++++++-------
 src/src/functions.h                |   2 +-
 src/src/globals.c                  |   4 +-
 src/src/globals.h                  |   4 +-
 src/src/readconf.c                 |  38 +++----
 src/src/route.c                    |   2 +-
 src/src/routers/manualroute.c      |  48 +++++----
 src/src/routers/queryprogram.c     |   6 +-
 src/src/routers/redirect.c         |   2 +-
 src/src/routers/rf_get_transport.c |   4 +-
 src/src/routers/rf_queue_add.c     |  97 +++++++++---------
 src/src/smtp_out.c                 |   6 +-
 src/src/structs.h                  |  22 +---
 src/src/tls-gnu.c                  |  19 ++--
 src/src/tls-openssl.c              |  15 +--
 src/src/tls.c                      |   6 +-
 src/src/transport.c                |  20 ++--
 src/src/transports/appendfile.c    | 120 +++++++++++-----------
 src/src/transports/appendfile.h    |   2 +-
 src/src/transports/autoreply.c     | 101 +++++++++----------
 src/src/transports/autoreply.h     |   2 +-
 src/src/transports/lmtp.c          |  42 ++++----
 src/src/transports/lmtp.h          |   2 +-
 src/src/transports/pipe.c          |  82 +++++++--------
 src/src/transports/pipe.h          |   2 +-
 src/src/transports/queuefile.c     |  41 ++++----
 src/src/transports/queuefile.h     |   2 +-
 src/src/transports/smtp.c          |  68 +++++++------
 src/src/transports/smtp.h          |   2 +-
 src/src/transports/smtp_socks.c    |   8 +-
 src/src/verify.c                   |  34 ++++---
 33 files changed, 558 insertions(+), 534 deletions(-)


diff --git a/src/src/deliver.c b/src/src/deliver.c
index a4ec5f798..f383ab9be 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -680,7 +680,7 @@ else if (testflag(addr, af_homonym))
   {
   if (addr->transport)
     tree_add_nonrecipient(
-      string_sprintf("%s/%s", addr->unique + 3, addr->transport->name));
+      string_sprintf("%s/%s", addr->unique + 3, addr->transport->drinst.name));
   }


 /* Non-homonymous child address */
@@ -904,7 +904,7 @@ const uschar * save_local =  deliver_localpart;
 const uschar * save_host = deliver_host;
 const uschar * save_address = deliver_host_address;
 const uschar * save_rn = router_name;
-uschar * save_tn = transport_name;
+const uschar * save_tn = transport_name;
 const int      save_port =   deliver_host_port;


 router_name =    addr->router ? addr->router->drinst.name : NULL;
@@ -925,13 +925,14 @@ if (!addr->transport)
   }
 else
   {
-  transport_name = addr->transport->name;
+  const uschar * dr_name = addr->transport->drinst.driver_name;


+  transport_name = addr->transport->drinst.name;
   (void) event_raise(addr->transport->event_action, event,
         addr->host_used
-        || Ustrcmp(addr->transport->driver_name, "smtp") == 0
-        || Ustrcmp(addr->transport->driver_name, "lmtp") == 0
-        || Ustrcmp(addr->transport->driver_name, "autoreply") == 0
+        || Ustrcmp(dr_name, "smtp") == 0
+        || Ustrcmp(dr_name, "lmtp") == 0
+        || Ustrcmp(dr_name, "autoreply") == 0
        ? addr->message : NULL,
        NULL);
   }
@@ -1034,7 +1035,8 @@ so won't necessarily look like a path. Add extra text for this case. */
 if (  testflag(addr, af_pfr)
    || (  success
       && addr->router && addr->router->log_as_local
-      && addr->transport && addr->transport->info->local
+      && addr->transport
+      && ((transport_info *)addr->transport->drinst.info)->local
    )  )
   {
   if (testflag(addr, af_file) && addr->local_part[0] != '/')
@@ -1180,14 +1182,14 @@ if (msg)
 if (addr->router)
   g = string_append(g, 2, US" R=", addr->router->drinst.name);


-g = string_append(g, 2, US" T=", addr->transport->name);
+g = string_append(g, 2, US" T=", addr->transport->drinst.name);

if (LOGGING(delivery_size))
g = string_fmt_append(g, " S=%d", transport_count);

/* Local delivery */

-if (addr->transport->info->local)
+if (((transport_info *)addr->transport->drinst.info)->local)
   {
   if (addr->host_list)
     g = string_append(g, 2, US" H=", addr->host_list->name);
@@ -1262,7 +1264,8 @@ else


 if (  LOGGING(smtp_confirmation)
    && addr->message
-   && (addr->host_used || Ustrcmp(addr->transport->driver_name, "lmtp") == 0)
+   && (  addr->host_used
+      || Ustrcmp(addr->transport->drinst.driver_name, "lmtp") == 0)
    )
   {
   unsigned lim = big_buffer_size < 1024 ? big_buffer_size : 1024;
@@ -1409,7 +1412,7 @@ if (used_return_path && LOGGING(return_path_on_delivery))
 if (addr->router)
   g = string_append(g, 2, US" R=", addr->router->drinst.name);
 if (addr->transport)
-  g = string_append(g, 2, US" T=", addr->transport->name);
+  g = string_append(g, 2, US" T=", addr->transport->drinst.name);


 if (addr->host_used)
   g = d_hostlog(g, addr);
@@ -1478,7 +1481,7 @@ if (driver_type == EXIM_DTYPE_TRANSPORT)
   {
   if (addr->transport)
     {
-    driver_name = addr->transport->name;
+    driver_name = addr->transport->drinst.name;
     driver_kind = US" transport";
     f.disable_logging = addr->transport->disable_logging;
     }
@@ -1532,7 +1535,7 @@ if (addr->return_file >= 0 && addr->return_filename)


   if (fstat(addr->return_file, &statbuf) == 0 && statbuf.st_size > 0)
     {
-    transport_instance *tb = addr->transport;
+    transport_instance * tb = addr->transport;


     /* Handle logging options */


@@ -1541,11 +1544,11 @@ if (addr->return_file >= 0 && addr->return_filename)
        || result == DEFER && tb->log_defer_output
        )
       {
-      uschar *s;
-      FILE *f = Ufopen(addr->return_filename, "rb");
+      uschar * s;
+      FILE * f = Ufopen(addr->return_filename, "rb");
       if (!f)
         log_write(0, LOG_MAIN|LOG_PANIC, "failed to open %s to log output "
-          "from %s transport: %s", addr->return_filename, tb->name,
+          "from %s transport: %s", addr->return_filename, tb->drinst.name,
           strerror(errno));
       else
         if ((s = US Ufgets(big_buffer, big_buffer_size, f)))
@@ -1556,7 +1559,7 @@ if (addr->return_file >= 0 && addr->return_filename)
           *p = 0;
           sp = string_printing(big_buffer);
           log_write(0, LOG_MAIN, "<%s>: %s transport output: %s",
-            addr->address, tb->name, sp);
+            addr->address, tb->drinst.name, sp);
           }
       (void)fclose(f);
       }
@@ -1858,8 +1861,8 @@ if (tp->gid_set)
 else if (tp->expand_gid)
   {
   GET_OPTION("group");
-  if (!route_find_expanded_group(tp->expand_gid, tp->name, US"transport", gidp,
-    &addr->message))
+  if (!route_find_expanded_group(tp->expand_gid, tp->drinst.name, US"transport",
+    gidp, &addr->message))
     {
     common_error(FALSE, addr, ERRNO_GIDFAIL, NULL);
     return FALSE;
@@ -1886,8 +1889,8 @@ else if (tp->expand_uid)
   {
   struct passwd *pw;
   GET_OPTION("user");
-  if (!route_find_expanded_user(tp->expand_uid, tp->name, US"transport", &pw,
-       uidp, &(addr->message)))
+  if (!route_find_expanded_user(tp->expand_uid, tp->drinst.name, US"transport",
+    &pw, uidp, &(addr->message)))
     {
     common_error(FALSE, addr, ERRNO_UIDFAIL, NULL);
     return FALSE;
@@ -1940,7 +1943,7 @@ a uid, it must also provide a gid. */
 if (!gid_set)
   {
   common_error(TRUE, addr, ERRNO_GIDFAIL, US"User set without group for "
-    "%s transport", tp->name);
+    "%s transport", tp->drinst.name);
   return FALSE;
   }


@@ -1955,7 +1958,7 @@ nuname = check_never_users(*uidp, never_users)
 if (nuname)
   {
   common_error(TRUE, addr, ERRNO_UIDFAIL, US"User %ld set for %s transport "
-    "is on the %s list", (long int)(*uidp), tp->name, nuname);
+    "is on the %s list", (long int)(*uidp), tp->drinst.name, nuname);
   return FALSE;
   }


@@ -1999,9 +2002,9 @@ if (expand_string_message)
   rc = DEFER;
   addr->message = size_limit == -1
     ? string_sprintf("failed to expand message_size_limit "
-      "in %s transport: %s", tp->name, expand_string_message)
+      "in %s transport: %s", tp->drinst.name, expand_string_message)
     : string_sprintf("invalid message_size_limit "
-      "in %s transport: %s", tp->name, expand_string_message);
+      "in %s transport: %s", tp->drinst.name, expand_string_message);
   }
 else if (size_limit > 0 && message_size > size_limit)
   {
@@ -2038,13 +2041,14 @@ static BOOL
 previously_transported(address_item *addr, BOOL testing)
 {
 uschar * s = string_sprintf("%s/%s",
-  addr->unique + (testflag(addr, af_homonym) ? 3:0), addr->transport->name);
+  addr->unique + (testflag(addr, af_homonym) ? 3:0),
+  addr->transport->drinst.name);


 if (tree_search(tree_nonrecipients, s) != 0)
   {
   DEBUG(D_deliver|D_route|D_transport)
     debug_printf("%s was previously delivered (%s transport): discarded\n",
-    addr->address, addr->transport->name);
+    addr->address, addr->transport->drinst.name);
   if (!testing) child_done(addr, tod_stamp(tod_log));
   return TRUE;
   }
@@ -2142,7 +2146,8 @@ int pfd[2];
 pid_t pid;
 uschar *working_directory;
 address_item *addr2;
-transport_instance *tp = addr->transport;
+transport_instance * tp = addr->transport;
+const uschar * trname = tp->drinst.name;


 /* Set up the return path from the errors or sender address. If the transport
 has its own return path setting, expand it and replace the existing value. */
@@ -2162,7 +2167,7 @@ if (tp->return_path)
     {
     common_error(TRUE, addr, ERRNO_EXPANDFAIL,
       US"Failed to expand return path \"%s\" in %s transport: %s",
-      tp->return_path, tp->name, expand_string_message);
+      tp->return_path, trname, expand_string_message);
     return;
     }
   }
@@ -2193,14 +2198,14 @@ if (  (deliver_home = tp->home_dir)        /* Set in transport, or */
   if (!(deliver_home = expand_string(rawhome)))
     {
     common_error(TRUE, addr, ERRNO_EXPANDFAIL, US"home directory \"%s\" failed "
-      "to expand for %s transport: %s", rawhome, tp->name,
+      "to expand for %s transport: %s", rawhome, trname,
       expand_string_message);
     return;
     }
   if (*deliver_home != '/')
     {
     common_error(TRUE, addr, ERRNO_NOTABSOLUTE, US"home directory path \"%s\" "
-      "is not absolute for %s transport", deliver_home, tp->name);
+      "is not absolute for %s transport", deliver_home, trname);
     return;
     }
   }
@@ -2220,14 +2225,14 @@ if (working_directory)
   if (!(working_directory = expand_string(raw)))
     {
     common_error(TRUE, addr, ERRNO_EXPANDFAIL, US"current directory \"%s\" "
-      "failed to expand for %s transport: %s", raw, tp->name,
+      "failed to expand for %s transport: %s", raw, trname,
       expand_string_message);
     return;
     }
   if (*working_directory != '/')
     {
     common_error(TRUE, addr, ERRNO_NOTABSOLUTE, US"current directory path "
-      "\"%s\" is not absolute for %s transport", working_directory, tp->name);
+      "\"%s\" is not absolute for %s transport", working_directory, trname);
     return;
     }
   }
@@ -2252,7 +2257,7 @@ if (  !shadowing
   if ((addr->return_file = open_msglog_file(addr->return_filename, 0400, &error)) < 0)
     {
     common_error(TRUE, addr, errno, US"Unable to %s file for %s transport "
-      "to return message: %s", error, tp->name, strerror(errno));
+      "to return message: %s", error, trname, strerror(errno));
     return;
     }
   }
@@ -2349,7 +2354,7 @@ if ((pid = exim_fork(US"delivery-local")) == 0)
     FD_CLOEXEC);
   exim_setugid(uid, gid, use_initgroups,
     string_sprintf("local delivery to %s <%s> transport=%s", addr->local_part,
-      addr->address, addr->transport->name));
+      addr->address, addr->transport->drinst.name));


   DEBUG(D_deliver)
     {
@@ -2373,14 +2378,14 @@ if ((pid = exim_fork(US"delivery-local")) == 0)
     {
     BOOL ok = TRUE;
     set_process_info("delivering %s to %s using %s", message_id,
-     addr->local_part, tp->name);
+     addr->local_part, trname);


     /* Setting these globals in the subprocess means we need never clear them */


-    transport_name = tp->name;
+    transport_name = trname;
     if (addr->router) router_name = addr->router->drinst.name;
-    driver_srcfile = tp->srcfile;
-    driver_srcline = tp->srcline;
+    driver_srcfile = tp->drinst.srcfile;
+    driver_srcline = tp->drinst.srcline;


     /* If a transport filter has been specified, set up its argument list.
     Any errors will get put into the address, and FALSE yielded. */
@@ -2396,8 +2401,9 @@ if ((pid = exim_fork(US"delivery-local")) == 0)


     if (ok)
       {
+      transport_info * ti = tp->drinst.info;
       debug_print_string(tp->debug_string);
-      replicate = !(tp->info->code)(addr->transport, addr);
+      replicate = !(ti->code)(addr->transport, addr);
       }
     }


@@ -2552,7 +2558,7 @@ if (!shadowing)
     if (addr2->transport_return == OK)
       {
       if (testflag(addr2, af_homonym))
-    sprintf(CS big_buffer, "%.500s/%s\n", addr2->unique + 3, tp->name);
+    sprintf(CS big_buffer, "%.500s/%s\n", addr2->unique + 3, trname);
       else
     sprintf(CS big_buffer, "%.500s\n", addr2->unique);


@@ -2587,7 +2593,7 @@ while ((rc = wait(&status)) != pid)
   if (rc < 0 && errno == ECHILD)      /* Process has vanished */
     {
     log_write(0, LOG_MAIN, "%s transport process vanished unexpectedly",
-      addr->transport->driver_name);
+      addr->transport->drinst.driver_name);
     status = 0;
     break;
     }
@@ -2601,7 +2607,7 @@ if ((status & 0xffff) != 0)
     addr->special_action = SPECIAL_FREEZE;
   log_write(0, LOG_MAIN|LOG_PANIC, "%s transport process returned non-zero "
     "status 0x%04x: %s %d",
-    addr->transport->driver_name,
+    addr->transport->drinst.driver_name,
     status,
     msb == 0 ? "terminated by signal" : "exit code",
     code);
@@ -2623,7 +2629,7 @@ if (addr->special_action == SPECIAL_WARN)
     if (!(warn_message = expand_string(warn_message)))
       log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand \"%s\" (warning "
     "message for %s transport): %s", addr->transport->warn_message,
-    addr->transport->name, expand_string_message);
+    addr->transport->drinst.name, expand_string_message);


     else if ((pid = child_open_exim(&fd, US"tpt-warning-message")) > 0)
       {
@@ -2656,6 +2662,7 @@ the key for the hints database used for the concurrency count. */
 static BOOL
 tpt_parallel_check(transport_instance * tp, address_item * addr, uschar ** key)
 {
+const uschar * trname = tp->drinst.name;
 unsigned max_parallel;


 GET_OPTION("max_parallel");
@@ -2665,20 +2672,20 @@ max_parallel = (unsigned) expand_string_integer(tp->max_parallel, TRUE);
 if (expand_string_message)
   {
   log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand max_parallel option "
-    "in %s transport (%s): %s", tp->name, addr->address,
+    "in %s transport (%s): %s", trname, addr->address,
     expand_string_message);
   return TRUE;
   }


 if (max_parallel > 0)
   {
-  uschar * serialize_key = string_sprintf("tpt-serialize-%s", tp->name);
+  uschar * serialize_key = string_sprintf("tpt-serialize-%s", trname);
   if (!enq_start(serialize_key, max_parallel))
     {
     address_item * next;
     DEBUG(D_transport)
       debug_printf("skipping tpt %s because concurrency limit %u reached\n",
-          tp->name, max_parallel);
+          trname, max_parallel);
     do
       {
       next = addr->next;
@@ -2724,8 +2731,9 @@ while (addr_local)
   address_item *addr2, *addr3, *nextaddr;
   int logflags = LOG_MAIN;
   int logchar = f.dont_deliver? '*' : '=';
-  transport_instance *tp;
+  transport_instance * tp;
   uschar * serialize_key = NULL;
+  const uschar * trname;


/* Pick the first undelivered address off the chain */

@@ -2748,6 +2756,7 @@ while (addr_local)
     post_process_one(addr, DEFER, logflags, EXIM_DTYPE_TRANSPORT, 0);
     continue;
     }
+  trname = tp->drinst.name;


   /* Check that this base address hasn't previously been delivered to this
   transport. The check is necessary at this point to handle homonymic addresses
@@ -2790,7 +2799,7 @@ while (addr_local)
       if (!batch_id)
         {
         log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand batch_id option "
-          "in %s transport (%s): %s", tp->name, addr->address,
+          "in %s transport (%s): %s", trname, addr->address,
           expand_string_message);
         batch_count = tp->batch_max;
         }
@@ -2847,7 +2856,7 @@ while (addr_local)
         if (!bid)
           {
           log_write(0, LOG_MAIN|LOG_PANIC, "Failed to expand batch_id option "
-            "in %s transport (%s): %s", tp->name, next->address,
+            "in %s transport (%s): %s", trname, next->address,
             expand_string_message);
           ok = FALSE;
           }
@@ -3048,15 +3057,15 @@ while (addr_local)


   if (  tp->shadow
      && (  !tp->shadow_condition
-        || expand_check_condition(tp->shadow_condition, tp->name, US"transport")
+        || expand_check_condition(tp->shadow_condition, trname, US"transport")
      )  )
     {
-    transport_instance *stp;
-    address_item *shadow_addr = NULL;
-    address_item **last = &shadow_addr;
+    transport_instance * stp;
+    address_item * shadow_addr = NULL;
+    address_item ** last = &shadow_addr;


-    for (stp = transports; stp; stp = stp->next)
-      if (Ustrcmp(stp->name, tp->shadow) == 0) break;
+    for (stp = transports; stp; stp = stp->drinst.next)
+      if (Ustrcmp(stp->drinst.name, tp->shadow) == 0) break;


     if (!stp)
       log_write(0, LOG_MAIN|LOG_PANIC, "shadow transport \"%s\" not found ",
@@ -3086,6 +3095,7 @@ while (addr_local)


     if (shadow_addr)
       {
+      const uschar * s_trname = stp->drinst.name;
       int save_count = transport_count;


       DEBUG(D_deliver|D_transport)
@@ -3097,8 +3107,8 @@ while (addr_local)
         int sresult = shadow_addr->transport_return;
         *(uschar **)shadow_addr->shadow_message =
       sresult == OK
-      ? string_sprintf(" ST=%s", stp->name)
-      : string_sprintf(" ST=%s (%s%s%s)", stp->name,
+      ? string_sprintf(" ST=%s", s_trname)
+      : string_sprintf(" ST=%s (%s%s%s)", s_trname,
           shadow_addr->basic_errno <= 0
           ? US""
           : US strerror(shadow_addr->basic_errno),
@@ -3113,7 +3123,7 @@ while (addr_local)


         DEBUG(D_deliver|D_transport)
           debug_printf("%s shadow transport returned %s for %s\n",
-            stp->name, rc_to_string(sresult), shadow_addr->address);
+            s_trname, rc_to_string(sresult), shadow_addr->address);
         }


       DEBUG(D_deliver|D_transport)
@@ -3142,7 +3152,7 @@ while (addr_local)


     DEBUG(D_deliver|D_transport)
       debug_printf("%s transport returned %s for %s\n",
-        tp->name, rc_to_string(result), addr2->address);
+        trname, rc_to_string(result), addr2->address);


     /* If there is a retry_record, or if delivery is deferred, build a retry
     item for setting a new retry time or deleting the old retry record from
@@ -3374,7 +3384,7 @@ while (!done)
     {
     msg = string_sprintf("got " SSIZE_T_FMT " of %d bytes (pipeheader) "
       "from transport process %ld for transport %s",
-      got, PIPE_HEADER_SIZE, (long)pid, addr->transport->driver_name);
+      got, PIPE_HEADER_SIZE, (long)pid, addr->transport->drinst.driver_name);
     done = TRUE;
     break;
     }
@@ -3393,7 +3403,7 @@ while (!done)
     {
     msg = string_sprintf("failed to read pipe "
       "from transport process %ld for transport %s: error decoding size from header",
-      (long)pid, addr ? addr->transport->driver_name : US"?");
+      (long)pid, addr ? addr->transport->drinst.driver_name : US"?");
     done = TRUE;
     break;
     }
@@ -3410,7 +3420,7 @@ while (!done)
     {
     msg = string_sprintf("got only " SSIZE_T_FMT " of " SIZE_T_FMT
       " bytes (pipedata) from transport process %ld for transport %s",
-      got, required, (long)pid, addr->transport->driver_name);
+      got, required, (long)pid, addr->transport->drinst.driver_name);
     done = TRUE;
     break;
     }
@@ -3600,7 +3610,7 @@ while (!done)
     ADDR_MISMATCH:
     msg = string_sprintf("address count mismatch for data read from pipe "
       "for transport process %ld for transport %s",
-        (long)pid, addrlist->transport->driver_name);
+        (long)pid, addrlist->transport->drinst.driver_name);
     done = TRUE;
     break;
     }
@@ -3788,7 +3798,7 @@ while (!done)
     default:
       msg = string_sprintf("malformed data (%d) read from pipe for transport "
     "process %ld for transport %s", ptr[-1], (long)pid,
-      addr ? addr->transport->driver_name : US"?");
+      addr ? addr->transport->drinst.driver_name : US"?");
       done = TRUE;
       break;
     }
@@ -3822,7 +3832,7 @@ something is wrong. */
 if (!msg && addr)
   msg = string_sprintf("insufficient address data read from pipe "
     "for transport process %ld for transport %s", (long)pid,
-      addr->transport->driver_name);
+      addr->transport->drinst.driver_name);


/* If an error message is set, something has gone wrong in getting back
the delivery data. Put the message into each address and freeze it. */
@@ -4149,7 +4159,7 @@ if ((status & 0xffff) != 0)

   msg = string_sprintf("%s transport process returned non-zero status 0x%04x: "
     "%s %d",
-    addrlist->transport->driver_name,
+    addrlist->transport->drinst.driver_name,
     status,
     msb == 0 ? "terminated by signal" : "exit code",
     code);
@@ -4217,7 +4227,7 @@ while (parcount > max)
     {
     transport_instance * tp = doneaddr->transport;
     if (tp->max_parallel)
-      enq_end(string_sprintf("tpt-serialize-%s", tp->name));
+      enq_end(string_sprintf("tpt-serialize-%s", tp->drinst.name));


     remote_post_process(doneaddr, LOG_MAIN, NULL, fallback);
     }
@@ -4392,7 +4402,7 @@ So look out for the place it gets used.
   if (tp->expand_multi_domain)
     deliver_set_expansions(addr);


-  if (exp_bool(addr, US"transport", tp->name, D_transport,
+  if (exp_bool(addr, US"transport", tp->drinst.name, D_transport,
         US"multi_domain", tp->multi_domain, tp->expand_multi_domain,
         &multi_domain) != OK)
     {
@@ -4503,7 +4513,7 @@ nonmatch domains
       || (  (
         (void)(!tp->expand_multi_domain || ((void)deliver_set_expansions(next), 1)),
             exp_bool(addr,
-            US"transport", next->transport->name, D_transport,
+            US"transport", next->transport->drinst.name, D_transport,
             US"multi_domain", next->transport->multi_domain,
             next->transport->expand_multi_domain, &md) == OK
             )
@@ -4614,7 +4624,7 @@ nonmatch domains
   f.continue_more = FALSE;           /* In case got set for the last lot */
   if (continue_transport)
     {
-    BOOL ok = Ustrcmp(continue_transport, tp->name) == 0;
+    BOOL ok = Ustrcmp(continue_transport, tp->drinst.name) == 0;
 /*XXX do we need to check for a DANEd conn vs. a change of domain? */


     /* If the transport is about to override the host list do not check
@@ -4625,11 +4635,11 @@ nonmatch domains


     if (ok)
       {
-      smtp_transport_options_block * ob;
+      transport_info * ti = tp->drinst.info;
+      smtp_transport_options_block * ob = tp->drinst.options_block;


-      if (  !(  Ustrcmp(tp->info->driver_name, "smtp") == 0
-         && (ob = (smtp_transport_options_block *)tp->options_block)
-         && ob->hosts_override && ob->hosts
+      if (  !(  Ustrcmp(ti->drinfo.driver_name, "smtp") == 0
+         && ob && ob->hosts_override && ob->hosts
          )
      && addr->host_list
      )
@@ -4648,8 +4658,8 @@ nonmatch domains
     if (!ok)
       {
       DEBUG(D_deliver) debug_printf("not suitable for continue_transport (%s)\n",
-    Ustrcmp(continue_transport, tp->name) != 0
-    ? string_sprintf("tpt %s vs %s", continue_transport, tp->name)
+    Ustrcmp(continue_transport, tp->drinst.name) != 0
+    ? string_sprintf("tpt %s vs %s", continue_transport, tp->drinst.name)
     : string_sprintf("no host matching %s", continue_hostname));
       if (serialize_key) enq_end(serialize_key);


@@ -4658,7 +4668,8 @@ nonmatch domains
     for (next = addr; ; next = next->next)
           {
           next->host_list = next->fallback_hosts;
-          DEBUG(D_deliver) debug_printf("%s queued for fallback host(s)\n", next->address);
+          DEBUG(D_deliver)
+        debug_printf("%s queued for fallback host(s)\n", next->address);
           if (!next->next) break;
           }
         next->next = addr_fallback;
@@ -4818,10 +4829,10 @@ do_remote_deliveries par_reduce par_wait par_read_pipe


     /* Setting these globals in the subprocess means we need never clear them */


-    transport_name = tp->name;
+    transport_name = tp->drinst.name;
     if (addr->router) router_name = addr->router->drinst.name;
-    driver_srcfile = tp->srcfile;
-    driver_srcline = tp->srcline;
+    driver_srcfile = tp->drinst.srcfile;
+    driver_srcline = tp->drinst.srcline;


     /* There are weird circumstances in which logging is disabled */
     f.disable_logging = tp->disable_logging;
@@ -4877,19 +4888,24 @@ do_remote_deliveries par_reduce par_wait par_read_pipe


     exim_setugid(uid, gid, use_initgroups,
       string_sprintf("remote delivery to %s with transport=%s",
-        addr->address, tp->name));
+        addr->address, tp->drinst.name));


     /* Close the unwanted half of this process' pipe, set the process state,
     and run the transport. Afterwards, transport_count will contain the number
     of bytes written. */


     (void)close(pfd[pipe_read]);
-    set_process_info("delivering %s using %s", message_id, tp->name);
+    set_process_info("delivering %s using %s", message_id, tp->drinst.name);
     debug_print_string(tp->debug_string);
-    if (!(tp->info->code)(addr->transport, addr)) replicate_status(addr);
+
+      {
+      transport_info * ti = tp->drinst.info;
+      if (!(ti->code)(addr->transport, addr))    /* Call the transport */
+    replicate_status(addr);
+      }


     set_process_info("delivering %s (just run %s for %s%s in subprocess)",
-      message_id, tp->name, addr->address, addr->next ? ", ..." : "");
+      message_id, tp->drinst.name, addr->address, addr->next ? ", ..." : "");


     /* Ensure any cached resources that we used are now released */


@@ -5478,10 +5494,11 @@ static int
 continue_closedown(void)
 {
 if (continue_transport)
-  for (transport_instance * t = transports; t; t = t->next)
-    if (Ustrcmp(t->name, continue_transport) == 0)
+  for (transport_instance * t = transports; t; t = t->drinst.next)
+    if (Ustrcmp(t->drinst.name, continue_transport) == 0)
       {
-      if (t->info->closedown) (t->info->closedown)(t);
+      transport_info * ti = t->drinst.info;
+      if (ti->closedown) (ti->closedown)(t);
       continue_transport = NULL;
       break;
       }
@@ -7211,8 +7228,8 @@ else if (system_filter && process_recipients != RECIP_FAIL_TIMEOUT)
         if (tpname)
           {
           transport_instance *tp;
-          for (tp = transports; tp; tp = tp->next)
-            if (Ustrcmp(tp->name, tpname) == 0)
+          for (tp = transports; tp; tp = tp->drinst.next)
+            if (Ustrcmp(tp->drinst.name, tpname) == 0)
               { p->transport = tp; break; }
           if (!tp)
             p->message = string_sprintf("failed to find \"%s\" transport "
@@ -7629,7 +7646,7 @@ while (addr_new)           /* Loop until all addresses dealt with */
     transport_instance * save_t = addr->transport;
     transport_instance * t = store_get(sizeof(*t), save_t);
     *t = *save_t;
-    t->name = US"**bypassed**";
+    t->drinst.name = US"**bypassed**";
     addr->transport = t;
         (void)post_process_one(addr, OK, LOG_MAIN, EXIM_DTYPE_TRANSPORT, '=');
         addr->transport= save_t;
@@ -7640,7 +7657,7 @@ while (addr_new)           /* Loop until all addresses dealt with */
       delivery. */


       DEBUG(D_deliver|D_route)
-        debug_printf("queued for %s transport\n", addr->transport->name);
+        debug_printf("queued for %s transport\n", addr->transport->drinst.name);
       addr->next = addr_local;
       addr_local = addr;
       continue;       /* with the next new address */
diff --git a/src/src/dns.c b/src/src/dns.c
index 45dc1574d..df6618593 100644
--- a/src/src/dns.c
+++ b/src/src/dns.c
@@ -1143,8 +1143,8 @@ not_good:
   if (!transport_name)
     s = event_action;
   else
-    for(transport_instance * tp = transports; tp; tp = tp->next)
-      if (Ustrcmp(tp->name, transport_name) == 0)
+    for(transport_instance * tp = transports; tp; tp = tp->drinst.next)
+      if (Ustrcmp(tp->drinst.name, transport_name) == 0)
     { s = tp->event_action; break; }


   if (s)
diff --git a/src/src/drtables.c b/src/src/drtables.c
index 6f3cffe1e..9872bc765 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -380,12 +380,14 @@ router_info routers_available[] = {
 transport_info transports_available[] = {
 #ifdef TRANSPORT_APPENDFILE
   {
-  .driver_name =    US"appendfile",
-  .options =        appendfile_transport_options,
-  .options_count =    &appendfile_transport_options_count,
-  .options_block =    &appendfile_transport_option_defaults,       /* private options defaults */
-  .options_len =    sizeof(appendfile_transport_options_block),
-  .init =        appendfile_transport_init,
+  .drinfo = {
+    .driver_name =    US"appendfile",
+    .options =        appendfile_transport_options,
+    .options_count =    &appendfile_transport_options_count,
+    .options_block =    &appendfile_transport_option_defaults,       /* private options defaults */
+    .options_len =    sizeof(appendfile_transport_options_block),
+    .init =        appendfile_transport_init,
+    },
   .code =        appendfile_transport_entry,
   .tidyup =        NULL,
   .closedown =        NULL,
@@ -394,12 +396,14 @@ transport_info transports_available[] = {
 #endif
 #ifdef TRANSPORT_AUTOREPLY
   {
-  .driver_name =    US"autoreply",
-  .options =        autoreply_transport_options,
-  .options_count =    &autoreply_transport_options_count,
-  .options_block =    &autoreply_transport_option_defaults,
-  .options_len =    sizeof(autoreply_transport_options_block),
-  .init =        autoreply_transport_init,
+  .drinfo = {
+    .driver_name =    US"autoreply",
+    .options =        autoreply_transport_options,
+    .options_count =    &autoreply_transport_options_count,
+    .options_block =    &autoreply_transport_option_defaults,
+    .options_len =    sizeof(autoreply_transport_options_block),
+    .init =        autoreply_transport_init,
+    },
   .code =        autoreply_transport_entry,
   .tidyup =        NULL,
   .closedown =        NULL,
@@ -408,12 +412,14 @@ transport_info transports_available[] = {
 #endif
 #ifdef TRANSPORT_LMTP
   {
-  .driver_name =    US"lmtp",
-  .options =        lmtp_transport_options,
-  .options_count =    &lmtp_transport_options_count,
-  .options_block =    &lmtp_transport_option_defaults,
-  .options_len =    sizeof(lmtp_transport_options_block),
-  .init =        lmtp_transport_init,
+  .drinfo = {
+    .driver_name =    US"lmtp",
+    .options =        lmtp_transport_options,
+    .options_count =    &lmtp_transport_options_count,
+    .options_block =    &lmtp_transport_option_defaults,
+    .options_len =    sizeof(lmtp_transport_options_block),
+    .init =        lmtp_transport_init,
+    },
   .code =        lmtp_transport_entry,
   .tidyup =        NULL,
   .closedown =        NULL,
@@ -422,12 +428,14 @@ transport_info transports_available[] = {
 #endif
 #ifdef TRANSPORT_PIPE
   {
-  .driver_name =    US"pipe",
-  .options =        pipe_transport_options,
-  .options_count =    &pipe_transport_options_count,
-  .options_block =    &pipe_transport_option_defaults,
-  .options_len =    sizeof(pipe_transport_options_block),
-  .init =        pipe_transport_init,
+  .drinfo = {
+    .driver_name =    US"pipe",
+    .options =        pipe_transport_options,
+    .options_count =    &pipe_transport_options_count,
+    .options_block =    &pipe_transport_option_defaults,
+    .options_len =    sizeof(pipe_transport_options_block),
+    .init =        pipe_transport_init,
+    },
   .code =        pipe_transport_entry,
   .tidyup =        NULL,
   .closedown =        NULL,
@@ -436,12 +444,14 @@ transport_info transports_available[] = {
 #endif
 #ifdef EXPERIMENTAL_QUEUEFILE
   {
-  .driver_name =    US"queuefile",
-  .options =        queuefile_transport_options,
-  .options_count =    &queuefile_transport_options_count,
-  .options_block =    &queuefile_transport_option_defaults,
-  .options_len =    sizeof(queuefile_transport_options_block),
-  .init =        queuefile_transport_init,
+  .drinfo = {
+    .driver_name =    US"queuefile",
+    .options =        queuefile_transport_options,
+    .options_count =    &queuefile_transport_options_count,
+    .options_block =    &queuefile_transport_option_defaults,
+    .options_len =    sizeof(queuefile_transport_options_block),
+    .init =        queuefile_transport_init,
+    },
   .code =        queuefile_transport_entry,
   .tidyup =        NULL,
   .closedown =        NULL,
@@ -450,12 +460,14 @@ transport_info transports_available[] = {
 #endif
 #ifdef TRANSPORT_SMTP
   {
-  .driver_name =    US"smtp",
-  .options =        smtp_transport_options,
-  .options_count =    &smtp_transport_options_count,
-  .options_block =    &smtp_transport_option_defaults,
-  .options_len =    sizeof(smtp_transport_options_block),
-  .init =        smtp_transport_init,
+  .drinfo = {
+    .driver_name =    US"smtp",
+    .options =        smtp_transport_options,
+    .options_count =    &smtp_transport_options_count,
+    .options_block =    &smtp_transport_option_defaults,
+    .options_len =    sizeof(smtp_transport_options_block),
+    .init =        smtp_transport_init,
+    },
   .code =        smtp_transport_entry,
   .tidyup =        NULL,
   .closedown =        smtp_transport_closedown,
diff --git a/src/src/functions.h b/src/src/functions.h
index 884b6fd77..e13f8044e 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -635,7 +635,7 @@ extern void    transport_init(void);
 extern const uschar *transport_rcpt_address(address_item *, BOOL);
 extern BOOL    transport_set_up_command(const uschar ***, const uschar *,
          unsigned, int, address_item *, const uschar *, uschar **);
-extern void    transport_update_waiting(host_item *, uschar *);
+extern void    transport_update_waiting(host_item *, const uschar *);
 extern BOOL    transport_write_block(transport_ctx *, uschar *, int, BOOL);
 extern void    transport_write_reset(int);
 extern BOOL    transport_write_string(int, const char *, ...);
diff --git a/src/src/globals.c b/src/src/globals.c
index 6f43b97d8..18ccc95a9 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -754,7 +754,7 @@ const uschar *continue_hostname      = NULL;
 const uschar *continue_host_address  = NULL;
 uschar  continue_next_id[MESSAGE_ID_LENGTH +1] = {[0]='\0'};
 int     continue_sequence      = 1;
-uschar *continue_transport     = NULL;
+const uschar *continue_transport = NULL;
 #ifndef COMPILE_UTILITY
 open_db *continue_retry_db     = NULL;
 open_db *continue_wait_db      = NULL;
@@ -1562,7 +1562,7 @@ transport_instance  transport_defaults = {
 };


 int     transport_count;
-uschar *transport_name          = NULL;
+const uschar *transport_name          = NULL;
 int     transport_newlines;
 const uschar **transport_filter_argv  = NULL;
 int     transport_filter_timeout;
diff --git a/src/src/globals.h b/src/src/globals.h
index 698bbd12f..8e75f7f93 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -459,7 +459,7 @@ extern const uschar *continue_hostname;      /* Host for continued delivery */
 extern const uschar *continue_host_address;  /* IP address for ditto */
 extern uschar  continue_next_id[];     /* Next message_id from hintsdb */
 extern int     continue_sequence;      /* Sequence num for continued delivery */
-extern uschar *continue_transport;     /* Transport for continued delivery */
+extern const uschar *continue_transport; /* Transport for continued delivery */
 #ifndef COMPILE_UTILITY
 extern open_db *continue_retry_db;     /* Hintsdb for retries */
 extern open_db *continue_wait_db;      /* Hintsdb for wait-transport */
@@ -1104,7 +1104,7 @@ extern int     timeout_frozen_after;   /* Max time to keep frozen messages */
 extern struct timeval timestamp_startup; /* For development measurements */
 #endif


-extern uschar *transport_name;         /* Name of transport last started */
+extern const 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 */
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 80b66a910..b79050f0c 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -662,44 +662,48 @@ if (router_name)
     }


 if (transport_name)
-  for (transport_instance * t = transports; t; t = t->next)
-    if (Ustrcmp(t->name, transport_name) == 0)
+  for (transport_instance * t = transports; t; t = t->drinst.next)
+    if (Ustrcmp(t->drinst.name, transport_name) == 0)
       {
-      const transport_info * ti = t->info;
+      const transport_info * ti = t->drinst.info;


       /* Check for a listptr match first */


-      for (optionlist * o = optionlist_transports;        /* generic options */
+      for (optionlist * o = optionlist_transports;    /* generic options */
       o < optionlist_transports + optionlist_transports_size; o++)
     if (  (o->type & opt_mask) == opt_stringptr
        && listptr == CS t + o->v.offset)
       return US o->name;


-      for (optionlist * o = ti->options;            /* private options */
-      o < ti->options + *ti->options_count; o++)
+      for (optionlist * o = ti->drinfo.options;        /* private options */
+      o < ti->drinfo.options + *ti->drinfo.options_count; o++)
     if (  (o->type & opt_mask) == opt_stringptr
-       && listptr == CS t->options_block + o->v.offset)
+       && listptr == CS t->drinst.options_block + o->v.offset)
       return US o->name;


       /* Check for a list addr match, unless null */


       if (!list) continue;


-      for (optionlist * o = optionlist_transports;        /* generic options */
+      for (optionlist * o = optionlist_transports;    /* generic options */
       o < optionlist_transports + optionlist_transports_size; o++)
     if (  (o->type & opt_mask) == opt_stringptr
        && list == * USS(CS t + o->v.offset))
-      if (name) return string_sprintf("DUP: %s %s vs. %s %s",
-        drname, name, t->name, o->name);
-      else { name = US o->name; drname = t->name; }
+      if (name)
+        return string_sprintf("DUP: %s %s vs. %s %s",
+                  drname, name, t->drinst.name, o->name);
+      else
+        { name = US o->name; drname = t->drinst.name; }


-      for (optionlist * o = ti->options;            /* private options */
-      o < ti->options + *ti->options_count; o++)
+      for (optionlist * o = ti->drinfo.options;        /* private options */
+      o < ti->drinfo.options + *ti->drinfo.options_count; o++)
     if (  (o->type & opt_mask) == opt_stringptr
-       && list == * USS(CS t->options_block + o->v.offset))
-      if (name) return string_sprintf("DUP: %s %s vs. %s %s",
-        drname, name, t->name, o->name);
-      else { name = US o->name; drname = t->name; }
+       && list == * USS(CS t->drinst.options_block + o->v.offset))
+      if (name)
+        return string_sprintf("DUP: %s %s vs. %s %s",
+                  drname, name, t->drinst.name, o->name);
+      else
+        { name = US o->name; drname = t->drinst.name; }
       }


 return name ? name : US"";
diff --git a/src/src/route.c b/src/src/route.c
index c7ea67609..b20e1ca0b 100644
--- a/src/src/route.c
+++ b/src/src/route.c
@@ -2039,7 +2039,7 @@ DEBUG(D_route)
   {
   debug_printf("  envelope to: %s\n", addr->address);
   debug_printf("  transport: %s\n", addr->transport
-    ? addr->transport->name : US"<none>");
+    ? addr->transport->drinst.name : US"<none>");


   if (addr->prop.errors_address)
     debug_printf("  errors to %s\n", addr->prop.errors_address);
diff --git a/src/src/routers/manualroute.c b/src/src/routers/manualroute.c
index e2062bc8e..05043a814 100644
--- a/src/src/routers/manualroute.c
+++ b/src/src/routers/manualroute.c
@@ -336,7 +336,7 @@ while (*options)
   const uschar * s = options;


Uskip_nonwhite(&options);
- n = options-s;
+ n = options - s;

   if (Ustrncmp(s, "randomize", n) == 0) randomize = TRUE;
   else if (Ustrncmp(s, "no_randomize", n) == 0) randomize = FALSE;
@@ -348,9 +348,9 @@ while (*options)
   else if (Ustrncmp(s, "ipv4_only",   n) == 0) lookup_type |= LK_IPV4_ONLY;
   else
     {
-    transport_instance *t;
-    for (t = transports; t; t = t->next)
-      if (Ustrncmp(t->name, s, n) == 0)
+    transport_instance * t;
+    for (t = transports; t; t = t->drinst.next)
+      if (Ustrncmp(t->drinst.name, s, n) == 0)
         {
         transport = t;
         individual_transport_set = TRUE;
@@ -399,28 +399,32 @@ if (!individual_transport_set)
 /* Deal with the case of a local transport. The host list is passed over as a
 single text string that ends up in $host. */


-if (transport && transport->info->local)
+if (transport)
   {
-  if (hostlist[0])
+  transport_info * ti = transport->drinst.info;
+  if (ti->local)
     {
-    host_item *h;
-    addr->host_list = h = store_get(sizeof(host_item), GET_UNTAINTED);
-    h->name = string_copy(hostlist);
-    h->address = NULL;
-    h->port = PORT_NONE;
-    h->mx = MX_NONE;
-    h->status = hstatus_unknown;
-    h->why = hwhy_unknown;
-    h->last_try = 0;
-    h->next = NULL;
-    }
+    if (hostlist[0])
+      {
+      host_item * h = store_get(sizeof(host_item), GET_UNTAINTED);
+      h->name = string_copy(hostlist);
+      h->address = NULL;
+      h->port = PORT_NONE;
+      h->mx = MX_NONE;
+      h->status = hstatus_unknown;
+      h->why = hwhy_unknown;
+      h->last_try = 0;
+      h->next = NULL;
+      addr->host_list = h;
+      }


-  /* There is nothing more to do other than to queue the address for the
-  local transport, filling in any uid/gid. This can be done by the common
-  rf_queue_add() function. */
+    /* There is nothing more to do other than to queue the address for the
+    local transport, filling in any uid/gid. This can be done by the common
+    rf_queue_add() function. */


-  addr->transport = transport;
-  return rf_queue_add(addr, addr_local, addr_remote, rblock, pw) ?  OK : DEFER;
+    addr->transport = transport;
+    return rf_queue_add(addr, addr_local, addr_remote, rblock, pw) ? OK : DEFER;
+    }
   }


/* There is either no transport (verify_only) or a remote transport. A host
diff --git a/src/src/routers/queryprogram.c b/src/src/routers/queryprogram.c
index 83ffe239a..82c3f2001 100644
--- a/src/src/routers/queryprogram.c
+++ b/src/src/routers/queryprogram.c
@@ -472,9 +472,9 @@ if ((s = expand_getkeyed(US"data", rdata)) && *s)

 if ((s = expand_getkeyed(US"transport", rdata)) && *s)
   {
-  transport_instance *transport;
-  for (transport = transports; transport; transport = transport->next)
-    if (Ustrcmp(transport->name, s) == 0) break;
+  transport_instance * transport;
+  for (transport = transports; transport; transport = transport->drinst.next)
+    if (Ustrcmp(transport->drinst.name, s) == 0) break;
   if (!transport)
     {
     addr->message = string_sprintf("unknown transport name %s yielded by "
diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c
index 97e609413..936cfca14 100644
--- a/src/src/routers/redirect.c
+++ b/src/src/routers/redirect.c
@@ -420,7 +420,7 @@ while (generated)
       next->address,
       testflag(next, af_pfr)? "pipe, file, or autoreply\n  " : "",
       next->prop.errors_address,
-      (next->transport == NULL)? US"NULL" : next->transport->name);
+      next->transport ? next->transport->drinst.name : US"NULL");


     if (testflag(next, af_uid_set))
       debug_printf("  uid=%ld ", (long int)(next->uid));
diff --git a/src/src/routers/rf_get_transport.c b/src/src/routers/rf_get_transport.c
index e6acca1b8..deabdf714 100644
--- a/src/src/routers/rf_get_transport.c
+++ b/src/src/routers/rf_get_transport.c
@@ -82,8 +82,8 @@ if (expandable)
 else
   ss = tpname;


-for (transport_instance * tp = transports; tp; tp = tp->next)
-  if (Ustrcmp(tp->name, ss) == 0)
+for (transport_instance * tp = transports; tp; tp = tp->drinst.next)
+  if (Ustrcmp(tp->drinst.name, ss) == 0)
     {
     DEBUG(D_route) debug_printf("set transport %s\n", ss);
     *tpptr = tp;
diff --git a/src/src/routers/rf_queue_add.c b/src/src/routers/rf_queue_add.c
index 8d94f5725..7f6936130 100644
--- a/src/src/routers/rf_queue_add.c
+++ b/src/src/routers/rf_queue_add.c
@@ -38,67 +38,74 @@ BOOL
 rf_queue_add(address_item *addr, address_item **paddr_local,
   address_item **paddr_remote, router_instance *rblock, struct passwd *pw)
 {
+transport_instance * t = addr->transport;
+
 addr->prop.domain_data = deliver_domain_data;         /* Save these values for */
 addr->prop.localpart_data = deliver_localpart_data;   /* use in the transport */


/* Handle a local transport */

-if (addr->transport && addr->transport->info->local)
+if (t)
   {
-  ugid_block ugid;
-
-  /* Default uid/gid and transport-time home directory are from the passwd file
-  when check_local_user is set, but can be overridden by explicit settings.
-  When getting the home directory out of the password information, set the
-  flag that prevents expansion later. */
-
-  if (pw)
+  transport_info * ti = t->drinst.info;
+  if (ti->local)
     {
-    addr->uid = pw->pw_uid;
-    addr->gid = pw->pw_gid;
-    setflag(addr, af_uid_set);
-    setflag(addr, af_gid_set);
-    setflag(addr, af_home_expanded);
-    addr->home_dir = string_copy(US pw->pw_dir);
+    ugid_block ugid;
+
+    /* Default uid/gid and transport-time home directory are from the passwd file
+    when check_local_user is set, but can be overridden by explicit settings.
+    When getting the home directory out of the password information, set the
+    flag that prevents expansion later. */
+
+    if (pw)
+      {
+      addr->uid = pw->pw_uid;
+      addr->gid = pw->pw_gid;
+      setflag(addr, af_uid_set);
+      setflag(addr, af_gid_set);
+      setflag(addr, af_home_expanded);
+      addr->home_dir = string_copy(US pw->pw_dir);
+      }
+
+    if (!rf_get_ugid(rblock, addr, &ugid)) return FALSE;
+    rf_set_ugid(addr, &ugid);
+
+    /* transport_home_directory (in rblock->home_directory) takes priority;
+    otherwise use the expanded value of router_home_directory. The flag also
+    tells the transport not to re-expand it. */
+
+    if (rblock->home_directory)
+      {
+      addr->home_dir = rblock->home_directory;
+      clearflag(addr, af_home_expanded);
+      }
+    else if (!addr->home_dir && testflag(addr, af_home_expanded))
+      addr->home_dir = deliver_home;
+
+    addr->current_dir = rblock->current_directory;
+
+    addr->next = *paddr_local;
+    *paddr_local = addr;
+    goto donelocal;
     }
-
-  if (!rf_get_ugid(rblock, addr, &ugid)) return FALSE;
-  rf_set_ugid(addr, &ugid);
-
-  /* transport_home_directory (in rblock->home_directory) takes priority;
-  otherwise use the expanded value of router_home_directory. The flag also
-  tells the transport not to re-expand it. */
-
-  if (rblock->home_directory)
-    {
-    addr->home_dir = rblock->home_directory;
-    clearflag(addr, af_home_expanded);
-    }
-  else if (!addr->home_dir && testflag(addr, af_home_expanded))
-    addr->home_dir = deliver_home;
-
-  addr->current_dir = rblock->current_directory;
-
-  addr->next = *paddr_local;
-  *paddr_local = addr;
   }


-/* For a remote transport, set up the fallback host list, and keep a count of
-the total number of addresses routed to remote transports. */
+/* For a remote transport or if we do not have one (eg verifying), set up the
+fallback host list, and keep a count of the total number of addresses routed
+to remote transports. */

-else
- {
- addr->fallback_hosts = rblock->fallback_hostlist;
- addr->next = *paddr_remote;
- *paddr_remote = addr;
- remote_delivery_count++;
- }
+addr->fallback_hosts = rblock->fallback_hostlist;
+addr->next = *paddr_remote;
+*paddr_remote = addr;
+remote_delivery_count++;
+
+donelocal:

 DEBUG(D_route)
   {
   debug_printf("queued for %s transport: local_part = %s\ndomain = %s\n"
     "  errors_to=%s\n",
-    addr->transport ? addr->transport->name : US"<unset>",
+    t ? t->drinst.name : US"<unset>",
     addr->local_part, addr->domain, addr->prop.errors_address);
   debug_printf("  domain_data=%s local_part_data=%s\n", addr->prop.domain_data,
     addr->prop.localpart_data);
diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c
index 1ff93b9e4..2ea29a7e4 100644
--- a/src/src/smtp_out.c
+++ b/src/src/smtp_out.c
@@ -261,8 +261,7 @@ int
 smtp_boundsock(smtp_connect_args * sc)
 {
 transport_instance * tb = sc->tblock;
-smtp_transport_options_block * ob =
-  (smtp_transport_options_block *)tb->options_block;
+smtp_transport_options_block * ob = tb->drinst.options_block;
 const uschar * dscp = ob->dscp;
 int sock, dscp_value, dscp_level, dscp_option;


@@ -338,8 +337,7 @@ Returns:      connected socket number, or -1 with errno set
 int
 smtp_sock_connect(smtp_connect_args * sc, int timeout, const blob * early_data)
 {
-smtp_transport_options_block * ob =
-  (smtp_transport_options_block *)sc->tblock->options_block;
+smtp_transport_options_block * ob = sc->tblock->drinst.options_block;
 int sock;
 int save_errno = 0;
 const blob * fastopen_blob = NULL;
diff --git a/src/src/structs.h b/src/src/structs.h
index ddebd18d5..73163b6c2 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -159,13 +159,7 @@ transports. They need to be generally accessible, however, as they are used by
 the main transport code. */


 typedef struct transport_instance {
-  struct transport_instance *next;
-  uschar *name;                   /* Instance name */
-  struct transport_info *info;    /* Info for this driver */
-  void *options_block;            /* Pointer to private options */
-  uschar *driver_name;            /* Must be first */
-  const uschar *srcfile;
-  int      srcline;
+  driver_instance drinst;


   int   (*setup)(                 /* Setup entry point */
     struct transport_instance *,
@@ -227,18 +221,12 @@ typedef struct transport_instance {
 } transport_instance;



-/* Structure for holding information about a type of transport. The first six
-fields must match driver_info above. */
+/* Structure for holding information about a type of transport. The first
+element must be a struct driver_info, to match auths and routers. */

 typedef struct transport_info {
-  uschar *driver_name;            /* Driver name */
-  optionlist *options;            /* Table of private options names */
-  int    *options_count;          /* -> Number of entries in table */
-  void   *options_block;          /* Points to default private block */
-  int     options_len;            /* Length of same in bytes */
-  void (*init)(                   /* Initialization function */
-    struct transport_instance *);
-/****/
+  driver_info drinfo;
+
   BOOL (*code)(                   /* Main entry point */
     transport_instance *,
     struct address_item *);
diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c
index 2d6cdb351..06cd4a5f8 100644
--- a/src/src/tls-gnu.c
+++ b/src/src/tls-gnu.c
@@ -1630,7 +1630,8 @@ and there seems little downside. */
 static void
 tls_client_creds_init(transport_instance * t, BOOL watch)
 {
-smtp_transport_options_block * ob = t->options_block;
+smtp_transport_options_block * ob = t->drinst.options_block;
+const uschar * trname = t->drinst.name;
 exim_gnutls_state_st tpt_dummy_state;
 host_item * dummy_host = (host_item *)1;
 uschar * dummy_errstr;
@@ -1663,7 +1664,7 @@ if (  opt_set_and_noexpand(ob->tls_certificate)
     const uschar * pkey = ob->tls_privatekey;


     DEBUG(D_tls)
-      debug_printf("TLS: preloading client certs for transport '%s'\n", t->name);
+      debug_printf("TLS: preloading client certs for transport '%s'\n", trname);


     /* The state->lib_state.x509_cred is used for the certs load, and is the sole
     structure element used.  So we can set up a dummy.  The hoat arg only
@@ -1677,7 +1678,7 @@ if (  opt_set_and_noexpand(ob->tls_certificate)
   }
 else
   DEBUG(D_tls)
-    debug_printf("TLS: not preloading client certs, for transport '%s'\n", t->name);
+    debug_printf("TLS: not preloading client certs, for transport '%s'\n", trname);


 /* If tls_verify_certificates is non-empty and has no $, load CAs.
 If none was configured and we can't handle "system", treat as empty. */
@@ -1691,7 +1692,7 @@ if (  opt_set_and_noexpand(ob->tls_verify_certificates)
   if (!watch || tls_set_watch(ob->tls_verify_certificates, FALSE))
     {
     DEBUG(D_tls)
-      debug_printf("TLS: preloading CA bundle for transport '%s'\n", t->name);
+      debug_printf("TLS: preloading CA bundle for transport '%s'\n", trname);
     if (creds_load_cabundle(&tpt_dummy_state, ob->tls_verify_certificates,
                 dummy_host, &dummy_errstr) != OK)
       return;
@@ -1701,19 +1702,19 @@ if (  opt_set_and_noexpand(ob->tls_verify_certificates)
       {
       if (!watch || tls_set_watch(ob->tls_crl, FALSE))
     {
-    DEBUG(D_tls) debug_printf("TLS: preloading CRL for transport '%s'\n", t->name);
+    DEBUG(D_tls) debug_printf("TLS: preloading CRL for transport '%s'\n", trname);
     if (creds_load_crl(&tpt_dummy_state, ob->tls_crl, &dummy_errstr) != OK)
       return;
     ob->tls_preload.crl = TRUE;
     }
       }
     else
-      DEBUG(D_tls) debug_printf("TLS: not preloading CRL, for transport '%s'\n", t->name);
+      DEBUG(D_tls) debug_printf("TLS: not preloading CRL, for transport '%s'\n", trname);
     }
   }
 else
   DEBUG(D_tls)
-      debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", t->name);
+      debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", trname);


 /* We do not preload tls_require_ciphers to to the transport as it implicitly
 depends on DANE or plain usage. */
@@ -1742,7 +1743,7 @@ state_server.lib_state = null_tls_preload;
 static void
 tls_client_creds_invalidate(transport_instance * t)
 {
-smtp_transport_options_block * ob = t->options_block;
+smtp_transport_options_block * ob = t->drinst.options_block;
 if (ob->tls_preload.x509_cred)
   gnutls_certificate_free_credentials(ob->tls_preload.x509_cred);
 ob->tls_preload = null_tls_preload;
@@ -3478,7 +3479,7 @@ tls_client_start(client_conn_ctx * cctx, smtp_connect_args * conn_args,
 host_item * host = conn_args->host;          /* for msgs and option-tests */
 transport_instance * tb = conn_args->tblock; /* always smtp or NULL */
 smtp_transport_options_block * ob = tb
-  ? (smtp_transport_options_block *)tb->options_block
+  ? tb->drinst.options_block
   : &smtp_transport_option_defaults;
 int rc;
 exim_gnutls_state_st * state = NULL;
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 0a5e2a7a0..033bd0e10 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1907,7 +1907,8 @@ a queue-run startup with watch clear. */
 static void
 tls_client_creds_init(transport_instance * t, BOOL watch)
 {
-smtp_transport_options_block * ob = t->options_block;
+smtp_transport_options_block * ob = t->drinst.options_block;
+const uschar * trname = t->drinst.name;
 exim_openssl_state_st tpt_dummy_state;
 host_item * dummy_host = (host_item *)1;
 uschar * dummy_errstr;
@@ -1934,7 +1935,7 @@ if (  opt_set_and_noexpand(ob->tls_certificate)
     uschar * pkey = ob->tls_privatekey;


     DEBUG(D_tls)
-      debug_printf("TLS: preloading client certs for transport '%s'\n",t->name);
+      debug_printf("TLS: preloading client certs for transport '%s'\n", trname);


     if (  tls_add_certfile(ctx, &tpt_dummy_state, ob->tls_certificate,
                     &dummy_errstr) == 0
@@ -1947,7 +1948,7 @@ if (  opt_set_and_noexpand(ob->tls_certificate)
   }
 else
   DEBUG(D_tls)
-    debug_printf("TLS: not preloading client certs, for transport '%s'\n", t->name);
+    debug_printf("TLS: not preloading client certs, for transport '%s'\n", trname);



 if (  opt_set_and_noexpand(ob->tls_verify_certificates)
@@ -1961,7 +1962,7 @@ if (  opt_set_and_noexpand(ob->tls_verify_certificates)
     {
     uschar * v_certs = ob->tls_verify_certificates;
     DEBUG(D_tls)
-      debug_printf("TLS: preloading CA bundle for transport '%s'\n", t->name);
+      debug_printf("TLS: preloading CA bundle for transport '%s'\n", trname);


     if (setup_certs(ctx, &v_certs,
       ob->tls_crl, dummy_host, &dummy_errstr) == OK)
@@ -1970,7 +1971,7 @@ if (  opt_set_and_noexpand(ob->tls_verify_certificates)
   }
 else
   DEBUG(D_tls)
-      debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", t->name);
+    debug_printf("TLS: not preloading CA bundle, for transport '%s'\n", trname);


 #endif /*EXIM_HAVE_INOTIFY*/
 }
@@ -1994,7 +1995,7 @@ state_server.u_ocsp.server.file_expanded = NULL;
 static void
 tls_client_creds_invalidate(transport_instance * t)
 {
-smtp_transport_options_block * ob = t->options_block;
+smtp_transport_options_block * ob = t->drinst.options_block;
 SSL_CTX_free(ob->tls_preload.lib_ctx);
 ob->tls_preload = null_tls_preload;
 }
@@ -4150,7 +4151,7 @@ tls_client_start(client_conn_ctx * cctx, smtp_connect_args * conn_args,
 host_item * host = conn_args->host;        /* for msgs and option-tests */
 transport_instance * tb = conn_args->tblock;    /* always smtp or NULL */
 smtp_transport_options_block * ob = tb
-  ? (smtp_transport_options_block *)tb->options_block
+  ? tb->drinst.options_block
   : &smtp_transport_option_defaults;
 exim_openssl_client_tls_ctx * exim_client_ctx;
 uschar * expciphers;
diff --git a/src/src/tls.c b/src/src/tls.c
index a1ae1abd1..5892491fc 100644
--- a/src/src/tls.c
+++ b/src/src/tls.c
@@ -324,8 +324,8 @@ struct timespec t = {0};
 void
 tls_client_creds_reload(BOOL watch)
 {
-for(transport_instance * t = transports; t; t = t->next)
-  if (Ustrcmp(t->driver_name, "smtp") == 0)
+for(transport_instance * t = transports; t; t = t->drinst.next)
+  if (Ustrcmp(t->drinst.driver_name, "smtp") == 0)
     {
 #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT)
     tls_client_creds_invalidate(t);
@@ -905,7 +905,7 @@ if (*sni)
   conn_args.tblock = tb = store_get(sizeof(*tb), GET_UNTAINTED);
   memset(tb, 0, sizeof(*tb));


- tb->options_block = ob = store_get(sizeof(*ob), GET_UNTAINTED);
+ tb->drinst.options_block = ob = store_get(sizeof(*ob), GET_UNTAINTED);
memcpy(ob, &smtp_transport_option_defaults, sizeof(*ob));

   ob->tls_sni = sni;
diff --git a/src/src/transport.c b/src/src/transport.c
index 170997172..3889a8529 100644
--- a/src/src/transport.c
+++ b/src/src/transport.c
@@ -44,7 +44,7 @@ optionlist optionlist_transports[] = {
   { "disable_logging",  opt_bool|opt_public,
                  LOFF(disable_logging) },
   { "driver",           opt_stringptr|opt_public,
-                 LOFF(driver_name) },
+                 LOFF(drinst.driver_name) },
   { "envelope_to_add",   opt_bool|opt_public,
                  LOFF(envelope_to_add) },
 #ifndef DISABLE_EVENT
@@ -102,11 +102,12 @@ uschar buf[64];


options_from_list(optionlist_transports, nelem(optionlist_transports), US"TRANSPORTS", NULL);

-for (transport_info * ti = transports_available; ti->driver_name[0]; ti++)
+for (transport_info * ti= transports_available; ti->drinfo.driver_name[0]; ti++)
   {
-  spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", ti->driver_name);
+  spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", ti->drinfo.driver_name);
   builtin_macro_create(buf);
-  options_from_list(ti->options, (unsigned)*ti->options_count, US"TRANSPORT", ti->driver_name);
+  options_from_list(ti->drinfo.options, (unsigned)*ti->drinfo.options_count,
+            US"TRANSPORT", ti->drinfo.driver_name);
   }
 }


@@ -156,16 +157,17 @@ readconf_driver_init(US"transport",
/* Now scan the configured transports and check inconsistencies. A shadow
transport is permitted only for local transports. */

-for (transport_instance * t = transports; t; t = t->next)
+for (transport_instance * t = transports; t; t = t->drinst.next)
   {
-  if (!t->info->local && t->shadow)
+  transport_info * ti = t->drinst.info;
+  if (!ti->local && t->shadow)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
-      "shadow transport not allowed on non-local transport %s", t->name);
+      "shadow transport not allowed on non-local transport %s", t->drinst.name);


   if (t->body_only && t->headers_only)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "%s transport: body_only and headers_only are mutually exclusive",
-      t->name);
+      t->drinst.name);
   }
 }


@@ -1497,7 +1499,7 @@ Returns:    nothing
 */


void
-transport_update_waiting(host_item * hostlist, uschar * tpname)
+transport_update_waiting(host_item * hostlist, const uschar * tpname)
{
const uschar * prevname = US"";
open_db dbblock, * dbp;
diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c
index eeb726ae1..14ef13c97 100644
--- a/src/src/transports/appendfile.c
+++ b/src/src/transports/appendfile.c
@@ -107,7 +107,7 @@ int appendfile_transport_options_count =

/* Dummy values */
appendfile_transport_options_block appendfile_transport_option_defaults = {0};
-void appendfile_transport_init(transport_instance *tblock) {}
+void appendfile_transport_init(driver_instance *tblock) {}
BOOL appendfile_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}

 #else    /*!MACRO_PREDEF*/
@@ -180,8 +180,8 @@ static int
 appendfile_transport_setup(transport_instance *tblock, address_item *addrlist,
   transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
 {
-appendfile_transport_options_block * ob =
-  (appendfile_transport_options_block *)(tblock->options_block);
+appendfile_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 uschar * q;
 double default_value = 0.0;


@@ -190,7 +190,7 @@ if (ob->expand_maildir_use_size_file)
   GET_OPTION("maildir_use_size_file");
   ob->maildir_use_size_file =
     expand_check_condition(ob->expand_maildir_use_size_file,
-        US"`maildir_use_size_file` in transport", tblock->name);
+        US"`maildir_use_size_file` in transport", trname);
   }


 /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size,
@@ -211,7 +211,7 @@ for (int i = 0; i < 5; i++)
     if (!(s =  expand_string(q)))
       {
       *errmsg = string_sprintf("Expansion of \"%s\" in %s transport failed: "
-        "%s", q, tblock->name, expand_string_message);
+        "%s", q, trname, expand_string_message);
       return f.search_find_defer ? DEFER : FAIL;
       }


@@ -231,7 +231,7 @@ for (int i = 0; i < 5; i++)
       else if ((int)d < 0 || (int)d > 100)
         {
         *errmsg = string_sprintf("Invalid quota_warn_threshold percentage (%d)"
-          " for %s transport", (int)d, tblock->name);
+          " for %s transport", (int)d, trname);
         return FAIL;
         }
       ob->quota_warn_threshold_is_percent = TRUE;
@@ -252,7 +252,7 @@ for (int i = 0; i < 5; i++)
     if (*rest)
       {
       *errmsg = string_sprintf("Malformed value \"%s\" (expansion of \"%s\") "
-        "in %s transport", s, q, tblock->name);
+        "in %s transport", s, q, trname);
       return FAIL;
       }
     }
@@ -306,7 +306,7 @@ for (int i = 0; i < 5; i++)
   if (which)
     {
     *errmsg = string_sprintf("%s value %.10g is too large (overflow) in "
-      "%s transport", which, d, tblock->name);
+      "%s transport", which, d, trname);
     return FAIL;
     }
   }
@@ -325,10 +325,11 @@ enable consistency checks to be done, or anything else that needs
 to be set up. */


void
-appendfile_transport_init(transport_instance *tblock)
+appendfile_transport_init(driver_instance * t)
{
-appendfile_transport_options_block *ob =
- (appendfile_transport_options_block *)(tblock->options_block);
+transport_instance * tblock = (transport_instance *)t;
+appendfile_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
uschar * s;

/* Set up the setup entry point, to be called in the privileged state */
@@ -343,7 +344,7 @@ if (ob->lock_retries == 0) ob->lock_retries = 1;

if (ob->filename && ob->dirname)
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n "
- "only one of \"file\" or \"directory\" can be specified", tblock->name);
+ "only one of \"file\" or \"directory\" can be specified", trname);

 /* If a file name was specified, neither quota_filecount nor quota_directory
 must be given. */
@@ -352,10 +353,10 @@ if (ob->filename)
   {
   if (ob->quota_filecount)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
-      "quota_filecount must not be set without \"directory\"", tblock->name);
+      "quota_filecount must not be set without \"directory\"", trname);
   if (ob->quota_directory)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
-      "quota_directory must not be set without \"directory\"", tblock->name);
+      "quota_directory must not be set without \"directory\"", trname);
   }


 /* The default locking depends on whether MBX is set or not. Change the
@@ -371,7 +372,7 @@ if (ob->use_flock)
   #ifdef NO_FLOCK
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
     "flock() support was not available in the operating system when this "
-    "binary was built", tblock->name);
+    "binary was built", trname);
   #endif  /* NO_FLOCK */
   if (!ob->set_use_fcntl) ob->use_fcntl = FALSE;
   }
@@ -395,7 +396,7 @@ if (ob->mbx_format)


 if (!ob->use_fcntl && !ob->use_flock && !ob->use_lockfile && !ob->use_mbx_lock)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
-    "no locking configured", tblock->name);
+    "no locking configured", trname);


/* Unset timeouts for non-used locking types */

@@ -410,20 +411,20 @@ if (ob->dirname)
   {
   if (ob->maildir_format && ob->mailstore_format)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
-      "only one of maildir and mailstore may be specified", tblock->name);
+      "only one of maildir and mailstore may be specified", trname);
   if (ob->quota_filecount != NULL && !ob->quota)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
-      "quota must be set if quota_filecount is set", tblock->name);
+      "quota must be set if quota_filecount is set", trname);
   if (ob->quota_directory != NULL && !ob->quota)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n  "
-      "quota must be set if quota_directory is set", tblock->name);
+      "quota must be set if quota_directory is set", trname);
   }


/* If a fixed uid field is set, then a gid field must also be set. */

 if (tblock->uid_set && !tblock->gid_set && !tblock->expand_gid)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
-    "user set without group for the %s transport", tblock->name);
+    "user set without group for the %s transport", trname);


 /* If "create_file" is set, check that a valid option is given, and set the
 integer variable. */
@@ -437,7 +438,7 @@ if ((s = ob->create_file_string ) && *s)
   else
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "invalid value given for \"create_file\" for the %s transport: '%s'",
-      tblock->name, s);
+      trname, s);
   ob->create_file = val;
   }


@@ -594,8 +595,8 @@ Returns:       pointer to the required transport, or NULL
 transport_instance *
 check_file_format(int cfd, transport_instance *tblock, address_item *addr)
 {
-const uschar *format =
-  ((appendfile_transport_options_block *)(tblock->options_block))->file_format;
+appendfile_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * format = ob->file_format;
 uschar data[256];
 int len = read(cfd, data, sizeof(data));
 int sep = 0;
@@ -618,11 +619,11 @@ while ((s = string_nextinlist(&format, &sep, big_buffer, big_buffer_size)))


   if (match && tp)
     {
-    for (transport_instance * tt = transports; tt; tt = tt->next)
-      if (Ustrcmp(tp, tt->name) == 0)
+    for (transport_instance * tt = transports; tt; tt = tt->drinst.next)
+      if (Ustrcmp(tp, tt->drinst.name) == 0)
         {
         DEBUG(D_transport)
-          debug_printf("file format -> %s transport\n", tt->name);
+          debug_printf("file format -> %s transport\n", tt->drinst.name);
         return tt;
         }
     addr->basic_errno = ERRNO_BADTRANSPORT;
@@ -1154,37 +1155,27 @@ appendfile_transport_entry(
   transport_instance *tblock,      /* data for this instantiation */
   address_item *addr)              /* address we are working on */
 {
-appendfile_transport_options_block *ob =
-  (appendfile_transport_options_block *)(tblock->options_block);
+appendfile_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 struct stat statbuf;
 const uschar * deliver_dir;
-uschar *fdname = NULL;
-uschar *filename = NULL;
-uschar *hitchname = NULL;
-uschar *dataname = NULL;
-uschar *lockname = NULL;
-uschar *newname = NULL;
-uschar *nametag = NULL;
-uschar *cr = US"";
-uschar *filecount_msg = US"";
-uschar *path;
+uschar * fdname = NULL, * filename = NULL;
+uschar * hitchname = NULL, * dataname = NULL;
+uschar * lockname = NULL, * newname = NULL;
+uschar * nametag = NULL, * cr = US"";
+uschar * filecount_msg = US"";
+uschar * path;
 struct utimbuf times;
 struct timeval msg_tv;
-BOOL disable_quota = FALSE;
-BOOL isdirectory = FALSE;
-BOOL isfifo = FALSE;
+BOOL disable_quota = FALSE, isdirectory = FALSE, isfifo = FALSE;
 BOOL wait_for_tick = FALSE;
 uid_t uid = geteuid();     /* See note above */
 gid_t gid = getegid();
 int mbformat;
-int mode = (addr->mode > 0) ? addr->mode : ob->mode;
-off_t saved_size = -1;
-off_t mailbox_size = ob->mailbox_size_value;
+int mode = addr->mode > 0 ? addr->mode : ob->mode;
+off_t saved_size = -1, mailbox_size = ob->mailbox_size_value;
 int mailbox_filecount = ob->mailbox_filecount_value;
-int hd = -1;
-int fd = -1;
-int yield = FAIL;
-int i;
+int hd = -1, fd = -1, yield = FAIL, i;


 #ifdef SUPPORT_MBX
 int save_fd = 0;
@@ -1240,7 +1231,7 @@ if (!fdname)
   if (!fdname)
     {
     addr->message = string_sprintf("Mandatory file or directory option "
-      "missing from %s transport", tblock->name);
+      "missing from %s transport", trname);
     goto ret_panic;
     }
   }
@@ -1251,14 +1242,14 @@ if ((ob->maildir_format || ob->mailstore_format) && !isdirectory)
   {
   addr->message = string_sprintf("mail%s_format requires \"directory\" "
     "to be specified for the %s transport",
-    ob->maildir_format ? "dir" : "store", tblock->name);
+    ob->maildir_format ? "dir" : "store", trname);
   goto ret_panic;
   }


 if (!(path = expand_string(fdname)))
   {
   addr->message = string_sprintf("Expansion of \"%s\" (file or directory "
-    "name for %s transport) failed: %s", fdname, tblock->name,
+    "name for %s transport) failed: %s", fdname, trname,
     expand_string_message);
   goto ret_panic;
   }
@@ -1333,7 +1324,7 @@ if (f.dont_deliver)
   {
   DEBUG(D_transport)
     debug_printf("*** delivery by %s transport bypassed by -N option\n",
-      tblock->name);
+      trname);
   addr->transport_return = OK;
   return FALSE;
   }
@@ -1390,7 +1381,7 @@ if (!isdirectory)
       addr->message =
         string_sprintf("failed to create directories for %s: %s", path,
           exim_errstr(errno));
-      DEBUG(D_transport) debug_printf("%s transport: %s\n", tblock->name, path);
+      DEBUG(D_transport) debug_printf("%s transport: %s\n", trname, path);
       return FALSE;
       }
     }
@@ -1418,11 +1409,12 @@ if (!isdirectory)
         {
         if (tt)
           {
+      transport_info * ti = tt->drinst.info;
           set_process_info("delivering %s to %s using %s", message_id,
-            addr->local_part, tt->name);
+            addr->local_part, tt->drinst.name);
           debug_print_string(tt->debug_string);
           addr->transport = tt;
-          (tt->info->code)(tt, addr);
+          (ti->code)(tt, addr);
           }
         return FALSE;
         }
@@ -2254,7 +2246,7 @@ else
         {
         addr->message = string_sprintf("Expansion of \"%s\" (quota_directory "
          "name for %s transport) failed: %s", ob->quota_directory,
-          tblock->name, expand_string_message);
+          trname, expand_string_message);
         goto ret_panic;
         }


@@ -2455,7 +2447,7 @@ else
     if (nametag && !expand_string(nametag) && !f.expand_string_forcedfail)
       {
       addr->message = string_sprintf("Expansion of \"%s\" (maildir_tag "
-        "for %s transport) failed: %s", nametag, tblock->name,
+        "for %s transport) failed: %s", nametag, trname,
         expand_string_message);
       goto ret_panic;
       }
@@ -2574,7 +2566,7 @@ else
       {
       addr->basic_errno = errno;
       addr->message = string_sprintf("fdopen of %s ("
-        "for %s transport) failed", filename, tblock->name);
+        "for %s transport) failed", filename, trname);
       (void)close(fd);
       Uunlink(filename);
       goto ret_panic;
@@ -2592,7 +2584,7 @@ else
           {
           addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
             "prefix for %s transport) failed: %s", ob->mailstore_prefix,
-            tblock->name, expand_string_message);
+            trname, expand_string_message);
           (void)fclose(env_file);
           Uunlink(filename);
           goto ret_panic;
@@ -2621,7 +2613,7 @@ else
           {
           addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
             "suffix for %s transport) failed: %s", ob->mailstore_suffix,
-            tblock->name, expand_string_message);
+            trname, expand_string_message);
           (void)fclose(env_file);
           Uunlink(filename);
           goto ret_panic;
@@ -2784,7 +2776,7 @@ if (yield == OK)
       errno = ERRNO_EXPANDFAIL;
       addr->transport_return = PANIC;
       addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s "
-    "transport) failed", ob->message_prefix, tblock->name);
+    "transport) failed", ob->message_prefix, trname);
       yield = DEFER;
       }
     else if (!transport_write_string(fd, "%s", prefix))
@@ -2850,7 +2842,7 @@ if (yield == OK)
       errno = ERRNO_EXPANDFAIL;
       addr->transport_return = PANIC;
       addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s "
-    "transport) failed", ob->message_suffix, tblock->name);
+    "transport) failed", ob->message_suffix, trname);
       yield = DEFER;
       }
     else if (!transport_write_string(fd, "%s", suffix))
@@ -3158,7 +3150,7 @@ else
             addr->transport_return = PANIC;
             addr->message = string_sprintf("Expansion of \"%s\" "
               "(directory_file for %s transport) failed: %s",
-              ob->dirfilename, tblock->name, expand_string_message);
+              ob->dirfilename, trname, expand_string_message);
             goto RETURN;
             }


@@ -3321,7 +3313,7 @@ return FALSE;

 tainted_ret_panic:
   addr->message = string_sprintf("Tainted '%s' (file or directory "
-      "name for %s transport) not permitted", path, tblock->name);
+      "name for %s transport) not permitted", path, trname);
 ret_panic:
   addr->transport_return = PANIC;
   return FALSE;
diff --git a/src/src/transports/appendfile.h b/src/src/transports/appendfile.h
index c3b7c59c4..3a637eb77 100644
--- a/src/src/transports/appendfile.h
+++ b/src/src/transports/appendfile.h
@@ -91,8 +91,8 @@ extern appendfile_transport_options_block appendfile_transport_option_defaults;


/* The main and init entry points for the transport */

+extern void appendfile_transport_init(driver_instance *);
extern BOOL appendfile_transport_entry(transport_instance *, address_item *);
-extern void appendfile_transport_init(transport_instance *);

/* Function that is shared with tf_maildir.c */

diff --git a/src/src/transports/autoreply.c b/src/src/transports/autoreply.c
index 5ffc07215..a6080695e 100644
--- a/src/src/transports/autoreply.c
+++ b/src/src/transports/autoreply.c
@@ -54,7 +54,7 @@ int autoreply_transport_options_count =

/* Dummy values */
autoreply_transport_options_block autoreply_transport_option_defaults = {0};
-void autoreply_transport_init(transport_instance *tblock) {}
+void autoreply_transport_init(driver_instance *tblock) {}
BOOL autoreply_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}

#else /*!MACRO_PREDEF*/
@@ -84,8 +84,9 @@ enable consistency checks to be done, or anything else that needs
to be set up. */

void
-autoreply_transport_init(transport_instance *tblock)
+autoreply_transport_init(driver_instance * t)
{
+transport_instance * tblock = (transport_instance *)t;
/*
autoreply_transport_options_block *ob =
(autoreply_transport_options_block *)(tblock->options_block);
@@ -95,7 +96,7 @@ autoreply_transport_options_block *ob =

 if (tblock->uid_set && !tblock->gid_set && tblock->expand_gid == NULL)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
-    "user set without group for the %s transport", tblock->name);
+    "user set without group for the %s transport", t->name);
 }



@@ -122,10 +123,11 @@ Returns:     expanded string if expansion succeeds;
              NULL otherwise
 */


-static uschar *
-checkexpand(uschar *s, address_item *addr, uschar *name, int type)
+static const uschar *
+checkexpand(const uschar * s, address_item * addr, const uschar * name,
+ int type)
{
-uschar *ss = expand_string(s);
+const uschar * ss = expand_cstring(s);

if (!ss)
{
@@ -135,7 +137,7 @@ if (!ss)
return NULL;
}

-if (type != cke_text) for (uschar * t = ss; *t != 0; t++)
+if (type != cke_text) for (const uschar * t = ss; *t; t++)
   {
   int c = *t;
   const uschar * sp;
@@ -168,8 +170,8 @@ Arguments:
 Returns:      edited replacement address list, or NULL, or original
 */


-static uschar *
-check_never_mail(uschar * list, const uschar * never_mail)
+static const uschar *
+check_never_mail(const uschar * list, const uschar * never_mail)
 {
 rmark reset_point = store_mark();
 uschar * newlist = string_copy(list);
@@ -262,27 +264,24 @@ autoreply_transport_entry(
   transport_instance *tblock,      /* data for this instantiation */
   address_item *addr)              /* address we are working on */
 {
+autoreply_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 int fd, pid, rc;
 int cache_fd = -1;
 int cache_size = 0;
 int add_size = 0;
 EXIM_DB * dbm_file = NULL;
 BOOL file_expand, return_message;
-uschar *from, *reply_to, *to, *cc, *bcc, *subject, *headers, *text, *file;
-uschar *logfile, *oncelog;
-uschar *cache_buff = NULL;
-uschar *cache_time = NULL;
-uschar *message_id = NULL;
-header_line *h;
+const uschar * from, * reply_to, * to, * cc, * bcc, * subject, * headers;
+const uschar * text, * file, * logfile, * oncelog;
+uschar * cache_buff = NULL, * cache_time = NULL, * message_id = NULL;
+header_line * h;
 time_t now = time(NULL);
 time_t once_repeat_sec = 0;
 FILE *fp;
 FILE *ff = NULL;


-autoreply_transport_options_block *ob =
- (autoreply_transport_options_block *)(tblock->options_block);
-
-DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
+DEBUG(D_transport) debug_printf("%s transport entered\n", trname);

/* Set up for the good case */

@@ -315,7 +314,7 @@ if (addr->reply)
}
else
{
- uschar * oncerepeat;
+ const uschar * oncerepeat;

   DEBUG(D_transport) debug_printf("taking data from transport\n");
   GET_OPTION("once_repeat");    oncerepeat = ob->once_repeat;
@@ -333,18 +332,18 @@ else
   file_expand = ob->file_expand;
   return_message = ob->return_message;


-  if (  from && !(from = checkexpand(from, addr, tblock->name, cke_hdr))
-     || reply_to && !(reply_to = checkexpand(reply_to, addr, tblock->name, cke_hdr))
-     || to && !(to = checkexpand(to, addr, tblock->name, cke_hdr))
-     || cc && !(cc = checkexpand(cc, addr, tblock->name, cke_hdr))
-     || bcc && !(bcc = checkexpand(bcc, addr, tblock->name, cke_hdr))
-     || subject && !(subject = checkexpand(subject, addr, tblock->name, cke_hdr))
-     || headers && !(headers = checkexpand(headers, addr, tblock->name, cke_text))
-     || text && !(text = checkexpand(text, addr, tblock->name, cke_text))
-     || file && !(file = checkexpand(file, addr, tblock->name, cke_file))
-     || logfile && !(logfile = checkexpand(logfile, addr, tblock->name, cke_file))
-     || oncelog && !(oncelog = checkexpand(oncelog, addr, tblock->name, cke_file))
-     || oncerepeat && !(oncerepeat = checkexpand(oncerepeat, addr, tblock->name, cke_file))
+  if (  from && !(from = checkexpand(from, addr, trname, cke_hdr))
+     || reply_to && !(reply_to = checkexpand(reply_to, addr, trname, cke_hdr))
+     || to && !(to = checkexpand(to, addr, trname, cke_hdr))
+     || cc && !(cc = checkexpand(cc, addr, trname, cke_hdr))
+     || bcc && !(bcc = checkexpand(bcc, addr, trname, cke_hdr))
+     || subject && !(subject = checkexpand(subject, addr, trname, cke_hdr))
+     || headers && !(headers = checkexpand(headers, addr, trname, cke_text))
+     || text && !(text = checkexpand(text, addr, trname, cke_text))
+     || file && !(file = checkexpand(file, addr, trname, cke_file))
+     || logfile && !(logfile = checkexpand(logfile, addr, trname, cke_file))
+     || oncelog && !(oncelog = checkexpand(oncelog, addr, trname, cke_file))
+     || oncerepeat && !(oncerepeat = checkexpand(oncerepeat, addr, trname, cke_file))
      )
     return FALSE;


@@ -353,7 +352,7 @@ else
       {
       addr->transport_return = FAIL;
       addr->message = string_sprintf("Invalid time value \"%s\" for "
-        "\"once_repeat\" in %s transport", oncerepeat, tblock->name);
+        "\"once_repeat\" in %s transport", oncerepeat, trname);
       return FALSE;
       }
   }
@@ -363,13 +362,13 @@ remove those that match. */


if (ob->never_mail)
{
- const uschar *never_mail = expand_string(ob->never_mail);
+ const uschar * never_mail = expand_string(ob->never_mail);

   if (!never_mail)
     {
     addr->transport_return = FAIL;
     addr->message = string_sprintf("Failed to expand \"%s\" for "
-      "\"never_mail\" in %s transport", ob->never_mail, tblock->name);
+      "\"never_mail\" in %s transport", ob->never_mail, trname);
     return FALSE;
     }


@@ -391,7 +390,7 @@ if (f.dont_deliver)
   {
   DEBUG(D_transport)
     debug_printf("*** delivery by %s transport bypassed by -N option\n",
-      tblock->name);
+      trname);
   return FALSE;
   }


@@ -412,7 +411,7 @@ if (oncelog && *oncelog && to)
     addr->transport_return = DEFER;
     addr->basic_errno = EACCES;
     addr->message = string_sprintf("Tainted '%s' (once file for %s transport)"
-      " not permitted", oncelog, tblock->name);
+      " not permitted", oncelog, trname);
     goto END_OFF;
     }


@@ -430,7 +429,7 @@ if (oncelog && *oncelog && to)
       addr->basic_errno = errno;
       addr->message = string_sprintf("Failed to %s \"once\" file %s when "
         "sending message from %s transport: %s",
-        cache_fd < 0 ? "open" : "stat", oncelog, tblock->name, strerror(errno));
+        cache_fd < 0 ? "open" : "stat", oncelog, trname, strerror(errno));
       goto END_OFF;
       }


@@ -483,7 +482,7 @@ if (oncelog && *oncelog && to)
       addr->transport_return = DEFER;
       addr->basic_errno = errno;
       addr->message = string_sprintf("Failed to open %s file %s when sending "
-        "message from %s transport: %s", EXIM_DBTYPE, oncelog, tblock->name,
+        "message from %s transport: %s", EXIM_DBTYPE, oncelog, trname,
         strerror(errno));
       goto END_OFF;
       }
@@ -508,7 +507,7 @@ if (oncelog && *oncelog && to)
       addr->transport_return = DEFER;
       addr->basic_errno = EACCES;
       addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)"
-    " not permitted", logfile, tblock->name);
+    " not permitted", logfile, trname);
       goto END_OFF;
       }


@@ -523,7 +522,7 @@ if (oncelog && *oncelog && to)
       if(write(log_fd, log_buffer, ptr - log_buffer) != ptr-log_buffer
         || close(log_fd))
         DEBUG(D_transport) debug_printf("Problem writing log file %s for %s "
-          "transport\n", logfile, tblock->name);
+          "transport\n", logfile, trname);
       }
     goto END_OFF;
     }
@@ -540,7 +539,7 @@ if (file)
     addr->transport_return = DEFER;
     addr->basic_errno = EACCES;
     addr->message = string_sprintf("Tainted '%s' (file for %s transport)"
-      " not permitted", file, tblock->name);
+      " not permitted", file, trname);
     return FALSE;
     }
   if (!(ff = Ufopen(file, "rb")) && !ob->file_optional)
@@ -548,7 +547,7 @@ if (file)
     addr->transport_return = DEFER;
     addr->basic_errno = errno;
     addr->message = string_sprintf("Failed to open file %s when sending "
-      "message from %s transport: %s", file, tblock->name, strerror(errno));
+      "message from %s transport: %s", file, trname, strerror(errno));
     return FALSE;
     }
   }
@@ -562,7 +561,7 @@ if ((pid = child_open_exim(&fd, US"autoreply")) < 0)
   addr->transport_return = DEFER;
   addr->basic_errno = errno;
   addr->message = string_sprintf("Failed to create child process to send "
-    "message from %s transport: %s", tblock->name, strerror(errno));
+    "message from %s transport: %s", trname, strerror(errno));
   DEBUG(D_transport) debug_printf("%s\n", addr->message);
   if (dbm_file) exim_dbclose(dbm_file);
   return FALSE;
@@ -716,7 +715,7 @@ if (cache_fd >= 0)
     memcpy(cache_time, &now, sizeof(time_t));
     if(write(cache_fd, from, size) != size)
       DEBUG(D_transport) debug_printf("Problem writing cache file %s for %s "
-    "transport\n", oncelog, tblock->name);
+    "transport\n", oncelog, trname);
     }
   }


@@ -727,7 +726,7 @@ else if (dbm_file)
   EXIM_DATUM key_datum, value_datum;
   exim_datum_init(&key_datum);          /* Some DBM libraries need to have */
   exim_datum_init(&value_datum);        /* cleared datums. */
-  exim_datum_data_set(&key_datum, to);
+  exim_datum_data_set(&key_datum, US to);   /*XXX rely on dbput not modifying */
   exim_datum_size_set(&key_datum, Ustrlen(to) + 1);


   /* Many OS define the datum value, sensibly, as a void *. However, there
@@ -747,13 +746,13 @@ if (rc != 0)
   if (rc == EXIT_NORECIPIENTS)
     {
     DEBUG(D_any) debug_printf("%s transport: message contained no recipients\n",
-      tblock->name);
+      trname);
     }
   else
     {
     addr->transport_return = DEFER;
     addr->message = string_sprintf("Failed to send message from %s "
-      "transport (%d)", tblock->name, rc);
+      "transport (%d)", trname, rc);
     goto END_OFF;
     }


@@ -792,17 +791,17 @@ if (logfile)
       g = string_fmt_append_f(g, SVFMT_TAINT_NOCHK, "  %s\n", headers);
     if(write(log_fd, g->s, g->ptr) != g->ptr || close(log_fd))
       DEBUG(D_transport) debug_printf("Problem writing log file %s for %s "
-        "transport\n", logfile, tblock->name);
+        "transport\n", logfile, trname);
     }
   else DEBUG(D_transport) debug_printf("Failed to open log file %s for %s "
-    "transport: %s\n", logfile, tblock->name, strerror(errno));
+    "transport: %s\n", logfile, trname, strerror(errno));
   }


END_OFF:
if (dbm_file) exim_dbclose(dbm_file);
if (cache_fd > 0) (void)close(cache_fd);

-DEBUG(D_transport) debug_printf("%s transport succeeded\n", tblock->name);
+DEBUG(D_transport) debug_printf("%s transport succeeded\n", trname);

return FALSE;
}
diff --git a/src/src/transports/autoreply.h b/src/src/transports/autoreply.h
index 83061719c..b15916bb1 100644
--- a/src/src/transports/autoreply.h
+++ b/src/src/transports/autoreply.h
@@ -40,7 +40,7 @@ extern autoreply_transport_options_block autoreply_transport_option_defaults;

/* The main and init entry points for the transport */

+extern void autoreply_transport_init(driver_instance *);
extern BOOL autoreply_transport_entry(transport_instance *, address_item *);
-extern void autoreply_transport_init(transport_instance *);

/* End of transports/autoreply.h */
diff --git a/src/src/transports/lmtp.c b/src/src/transports/lmtp.c
index 7f82ef708..ae9295292 100644
--- a/src/src/transports/lmtp.c
+++ b/src/src/transports/lmtp.c
@@ -49,7 +49,7 @@ int lmtp_transport_options_count =

/* Dummy values */
lmtp_transport_options_block lmtp_transport_option_defaults = {0};
-void lmtp_transport_init(transport_instance *tblock) {}
+void lmtp_transport_init(driver_instance *tblock) {}
BOOL lmtp_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}

#else /*!MACRO_PREDEF*/
@@ -76,33 +76,33 @@ enable consistency checks to be done, or anything else that needs
to be set up. */

void
-lmtp_transport_init(transport_instance *tblock)
+lmtp_transport_init(driver_instance * t)
{
-lmtp_transport_options_block *ob =
- (lmtp_transport_options_block *)(tblock->options_block);
+transport_instance * tblock = (transport_instance *)t;
+lmtp_transport_options_block * ob = t->options_block;

/* Either the command field or the socket field must be set */

 if ((ob->cmd == NULL) == (ob->skt == NULL))
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "one (and only one) of command or socket must be set for the %s transport",
-    tblock->name);
+    tblock->drinst.name);


/* If a fixed uid field is set, then a gid field must also be set. */

 if (tblock->uid_set && !tblock->gid_set && tblock->expand_gid == NULL)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
-    "user set without group for the %s transport", tblock->name);
+    "user set without group for the %s transport", tblock->drinst.name);


/* Set up the bitwise options for transport_write_message from the various
driver options. Only one of body_only and headers_only can be set. */

 ob->options |=
-  (tblock->body_only? topt_no_headers : 0) |
-  (tblock->headers_only? topt_no_body : 0) |
-  (tblock->return_path_add? topt_add_return_path : 0) |
-  (tblock->delivery_date_add? topt_add_delivery_date : 0) |
-  (tblock->envelope_to_add? topt_add_envelope_to : 0) |
+  (tblock->body_only        ? topt_no_headers : 0) |
+  (tblock->headers_only        ? topt_no_body : 0) |
+  (tblock->return_path_add    ? topt_add_return_path : 0) |
+  (tblock->delivery_date_add    ? topt_add_delivery_date : 0) |
+  (tblock->envelope_to_add    ? topt_add_envelope_to : 0) |
   topt_use_crlf | topt_end_dot;
 }


@@ -467,10 +467,10 @@ lmtp_transport_entry(
   transport_instance *tblock,      /* data for this instantiation */
   address_item *addrlist)          /* address(es) we are working on */
 {
+lmtp_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 pid_t pid = 0;
 FILE *out;
-lmtp_transport_options_block *ob =
-  (lmtp_transport_options_block *)(tblock->options_block);
 struct sockaddr_un sockun;         /* don't call this "sun" ! */
 int timeout = ob->timeout;
 int fd_in = -1, fd_out = -1;
@@ -482,7 +482,7 @@ uschar *sockname = NULL;
 const uschar **argv;
 uschar buffer[256];


-DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
+DEBUG(D_transport) debug_printf("%s transport entered\n", trname);

 /* Initialization ensures that either a command or a socket is specified, but
 not both. When a command is specified, call the common function for creating an
@@ -491,7 +491,7 @@ argument list and expanding the items. */
 if (ob->cmd)
   {
   DEBUG(D_transport) debug_printf("using command %s\n", ob->cmd);
-  sprintf(CS buffer, "%.50s transport", tblock->name);
+  sprintf(CS buffer, "%.50s transport", trname);
   if (!transport_set_up_command(&argv, ob->cmd, TSUC_EXPAND_ARGS, PANIC,
     addrlist, buffer, NULL))
     return FALSE;
@@ -508,7 +508,7 @@ leader, so we can kill it and all its children on an error. */
             US"lmtp-tpt-cmd")) < 0)
     {
     addrlist->message = string_sprintf(
-      "Failed to create child process for %s transport: %s", tblock->name,
+      "Failed to create child process for %s transport: %s", trname,
         strerror(errno));
     return FALSE;
     }
@@ -522,7 +522,7 @@ else
   if (!(sockname = expand_string(ob->skt)))
     {
     addrlist->message = string_sprintf("Expansion of \"%s\" (socket setting "
-      "for %s transport) failed: %s", ob->skt, tblock->name,
+      "for %s transport) failed: %s", ob->skt, trname,
       expand_string_message);
     return FALSE;
     }
@@ -530,7 +530,7 @@ else
     {
     addrlist->message = string_sprintf(
       "Failed to create socket %s for %s transport: %s",
-        ob->skt, tblock->name, strerror(errno));
+        ob->skt, trname, strerror(errno));
     return FALSE;
     }


@@ -544,7 +544,7 @@ else
     {
     addrlist->message = string_sprintf(
       "Failed to connect to socket %s for %s transport: %s",
-        sockun.sun_path, tblock->name, strerror(errno));
+        sockun.sun_path, trname, strerror(errno));
     return FALSE;
     }
   }
@@ -795,7 +795,7 @@ if (fd_in >= 0) (void)close(fd_in);
 if (fd_out >= 0) (void)fclose(out);


DEBUG(D_transport)
- debug_printf("%s transport yields %d\n", tblock->name, yield);
+ debug_printf("%s transport yields %d\n", trname, yield);

return yield;

@@ -803,7 +803,7 @@ return yield;
 MINUS_N:
   DEBUG(D_transport)
     debug_printf("*** delivery by %s transport bypassed by -N option",
-      tblock->name);
+      trname);
   addrlist->transport_return = OK;
   return FALSE;
 }
diff --git a/src/src/transports/lmtp.h b/src/src/transports/lmtp.h
index fe51b18cc..b1f0f0b06 100644
--- a/src/src/transports/lmtp.h
+++ b/src/src/transports/lmtp.h
@@ -27,7 +27,7 @@ extern lmtp_transport_options_block lmtp_transport_option_defaults;


/* The main and init entry points for the transport */

+extern void lmtp_transport_init(driver_instance *);
extern BOOL lmtp_transport_entry(transport_instance *, address_item *);
-extern void lmtp_transport_init(transport_instance *);

/* End of transports/lmtp.h */
diff --git a/src/src/transports/pipe.c b/src/src/transports/pipe.c
index faed1d00f..1b90c4314 100644
--- a/src/src/transports/pipe.c
+++ b/src/src/transports/pipe.c
@@ -82,7 +82,7 @@ int pipe_transport_options_count =

/* Dummy values */
pipe_transport_options_block pipe_transport_option_defaults = {0};
-void pipe_transport_init(transport_instance *tblock) {}
+void pipe_transport_init(driver_instance *tblock) {}
BOOL pipe_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}

#else /*!MACRO_PREDEF*/
@@ -126,8 +126,7 @@ static int
pipe_transport_setup(transport_instance *tblock, address_item *addrlist,
transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
{
-pipe_transport_options_block *ob =
- (pipe_transport_options_block *)(tblock->options_block);
+pipe_transport_options_block * ob = tblock->drinst.options_block;

#ifdef HAVE_SETCLASSRESOURCES
if (ob->use_classresources)
@@ -177,10 +176,11 @@ enable consistency checks to be done, or anything else that needs
to be set up. */

void
-pipe_transport_init(transport_instance *tblock)
+pipe_transport_init(driver_instance * t)
{
-pipe_transport_options_block *ob =
- (pipe_transport_options_block *)(tblock->options_block);
+transport_instance * tblock = (transport_instance *)t;
+const uschar * trname = t->name;
+pipe_transport_options_block * ob = t->options_block;

/* Set up the setup entry point, to be called in the privileged state */

@@ -192,13 +192,13 @@ if (tblock->deliver_as_creator && (tblock->uid_set || tblock->gid_set ||
   tblock->expand_uid != NULL || tblock->expand_gid != NULL))
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "both pipe_as_creator and an explicit uid/gid are set for the %s "
-        "transport", tblock->name);
+        "transport", trname);


/* If a fixed uid field is set, then a gid field must also be set. */

 if (tblock->uid_set && !tblock->gid_set && tblock->expand_gid == NULL)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
-    "user set without group for the %s transport", tblock->name);
+    "user set without group for the %s transport", trname);


 /* Temp_errors must consist only of digits and colons, but there can be
 spaces round the colons, so allow them too. */
@@ -209,7 +209,7 @@ if (ob->temp_errors != NULL && Ustrcmp(ob->temp_errors, "*") != 0)
   if (ob->temp_errors[p] != 0)
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "temp_errors must be a list of numbers or an asterisk for the %s "
-      "transport", tblock->name);
+      "transport", trname);
   }


 /* Only one of return_output/return_fail_output or log_output/log_fail_output
@@ -218,12 +218,12 @@ should be set. */
 if (tblock->return_output && tblock->return_fail_output)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "both return_output and return_fail_output set for %s transport",
-    tblock->name);
+    trname);


 if (tblock->log_output && tblock->log_fail_output)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "both log_output and log_fail_output set for the %s transport",
-    tblock->name);
+    trname);


 /* If batch SMTP is set, force the check and escape strings, and arrange that
 headers are also escaped. */
@@ -250,14 +250,14 @@ else
 if (ob->restrict_to_path && ob->use_shell)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "both restrict_to_path and use_shell set for %s transport",
-    tblock->name);
+    trname);


/* The allow_commands and use_shell options are incompatible */

 if (ob->allow_commands && ob->use_shell)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "both allow_commands and use_shell set for %s transport",
-    tblock->name);
+    trname);


 /* Set up the bitwise options for transport_write_message from the various
 driver options. Only one of body_only and headers_only can be set. */
@@ -295,8 +295,8 @@ Returns:             TRUE if all went well; otherwise an error will be


 static BOOL
 set_up_direct_command(const uschar *** argvptr, const uschar * cmd,
-  BOOL expand_arguments, int expand_fail, address_item * addr, uschar * tname,
-  pipe_transport_options_block * ob)
+  BOOL expand_arguments, int expand_fail, address_item * addr,
+  const uschar * tname, pipe_transport_options_block * ob)
 {
 BOOL permitted = FALSE;
 const uschar **argv;
@@ -419,7 +419,8 @@ Returns:             TRUE if all went well; otherwise an error will be


static BOOL
set_up_shell_command(const uschar *** argvptr, const uschar * cmd,
- BOOL expand_arguments, int expand_fail, address_item * addr, uschar * tname)
+ BOOL expand_arguments, int expand_fail, address_item * addr,
+ const uschar * tname)
{
const uschar **argv;

@@ -512,20 +513,15 @@ pipe_transport_entry(
   transport_instance *tblock,      /* data for this instantiation */
   address_item *addr)              /* address(es) we are working on */
 {
+pipe_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 pid_t pid, outpid;
 int fd_in, fd_out, rc;
-int envcount = 0;
-int envsep = 0;
-int expand_fail;
-pipe_transport_options_block *ob =
-  (pipe_transport_options_block *)(tblock->options_block);
-int timeout = ob->timeout;
-BOOL written_ok = FALSE;
-BOOL expand_arguments;
+int envcount = 0, envsep = 0, expand_fail, timeout = ob->timeout;
+BOOL written_ok = FALSE, expand_arguments;
 const uschar ** argv;
 uschar * envp[50];
-const uschar * envlist = ob->environment;
-const uschar * cmd;
+const uschar * envlist = ob->environment, * cmd;
 uschar * ss;
 uschar * eol = ob->use_crlf ? US"\r\n" : US"\n";
 transport_ctx tctx = {
@@ -536,7 +532,7 @@ transport_ctx tctx = {
   ob->options | topt_not_socket /* set at initialization time */
 };


-DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
+DEBUG(D_transport) debug_printf("%s transport entered\n", trname);

/* Set up for the good case */

@@ -582,14 +578,14 @@ if (!cmd || !*cmd)
   {
   addr->transport_return = DEFER;
   addr->message = string_sprintf("no command specified for %s transport",
-    tblock->name);
+    trname);
   return FALSE;
   }
 if (is_tainted(cmd))
   {
   DEBUG(D_transport) debug_printf("cmd '%s' is tainted\n", cmd);
   addr->message = string_sprintf("Tainted '%s' (command "
-    "for %s transport) not permitted", cmd, tblock->name);
+    "for %s transport) not permitted", cmd, trname);
   addr->transport_return = PANIC;
   return FALSE;
   }
@@ -618,10 +614,10 @@ there is an option to do that. */
 if (ob->use_shell)
   {
   if (!set_up_shell_command(&argv, cmd, expand_arguments, expand_fail, addr,
-    tblock->name)) return FALSE;
+    trname)) return FALSE;
   }
 else if (!set_up_direct_command(&argv, cmd, expand_arguments, expand_fail, addr,
-  tblock->name, ob)) return FALSE;
+  trname, ob)) return FALSE;


 expand_nmax = -1;           /* Reset */
 filter_thisaddress = NULL;
@@ -662,7 +658,7 @@ if (envlist)
     {
     addr->transport_return = DEFER;
     addr->message = string_sprintf("failed to expand string \"%s\" "
-      "for %s transport: %s", ob->environment, tblock->name,
+      "for %s transport: %s", ob->environment, trname,
       expand_string_message);
     return FALSE;
     }
@@ -674,7 +670,7 @@ while ((ss = string_nextinlist(&envlist, &envsep, NULL, 0)))
      addr->transport_return = DEFER;
      addr->basic_errno = E2BIG;
      addr->message = string_sprintf("too many environment settings for "
-       "%s transport", tblock->name);
+       "%s transport", trname);
      return FALSE;
      }
    envp[envcount++] = string_copy(ss);
@@ -688,7 +684,7 @@ if (f.dont_deliver)
   {
   DEBUG(D_transport)
     debug_printf("*** delivery by %s transport bypassed by -N option",
-      tblock->name);
+      trname);
   return FALSE;
   }


@@ -719,7 +715,7 @@ if ((pid = child_open(USS argv, envp, ob->umask, &fd_in, &fd_out, TRUE,
   {
   addr->transport_return = DEFER;
   addr->message = string_sprintf(
-    "Failed to create child process for %s transport: %s", tblock->name,
+    "Failed to create child process for %s transport: %s", trname,
       strerror(errno));
   return FALSE;
   }
@@ -733,7 +729,7 @@ if ((outpid = exim_fork(US"pipe-tpt-output")) < 0)
   addr->transport_return = DEFER;
   addr->message = string_sprintf(
     "Failed to create process for handling output in %s transport",
-      tblock->name);
+      trname);
   (void)close(fd_in);
   (void)close(fd_out);
   return FALSE;
@@ -811,7 +807,7 @@ if (ob->message_prefix)
     {
     addr->transport_return = f.search_find_defer? DEFER : PANIC;
     addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s "
-      "transport) failed: %s", ob->message_prefix, tblock->name,
+      "transport) failed: %s", ob->message_prefix, trname,
       expand_string_message);
     return FALSE;
     }
@@ -854,7 +850,7 @@ if (ob->message_suffix)
     {
     addr->transport_return = f.search_find_defer? DEFER : PANIC;
     addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s "
-      "transport) failed: %s", ob->message_suffix, tblock->name,
+      "transport) failed: %s", ob->message_suffix, trname,
       expand_string_message);
     return FALSE;
     }
@@ -948,7 +944,7 @@ if ((rc = child_close(pid, timeout)) != 0)
     {
     addr->transport_return = PANIC;
     addr->message = string_sprintf("Wait() failed for child process of %s "
-      "transport: %s%s", tblock->name, strerror(errno), tmsg);
+      "transport: %s%s", trname, strerror(errno), tmsg);
     }


   /* Since the transport_filter timed out we assume it has sent the child process
@@ -976,14 +972,14 @@ if ((rc = child_close(pid, timeout)) != 0)
       addr->transport_return = DEFER;
       addr->special_action = SPECIAL_FREEZE;
       addr->message = string_sprintf("Child process of %s transport (running "
-        "command \"%s\") was terminated by signal %d (%s)%s", tblock->name, cmd,
+        "command \"%s\") was terminated by signal %d (%s)%s", trname, cmd,
         -rc, os_strsignal(-rc), tmsg);
       }
     else if (!ob->ignore_status)
       {
       addr->transport_return = FAIL;
       addr->message = string_sprintf("Child process of %s transport (running "
-        "command \"%s\") was terminated by signal %d (%s)%s", tblock->name, cmd,
+        "command \"%s\") was terminated by signal %d (%s)%s", trname, cmd,
         -rc, os_strsignal(-rc), tmsg);
       }
     }
@@ -1069,7 +1065,7 @@ if ((rc = child_close(pid, timeout)) != 0)
       doesn't have to be brilliantly efficient - it is an error situation. */


       addr->message = string_sprintf("Child process of %s transport returned "
-        "%d", tblock->name, rc);
+        "%d", trname, rc);
       g = string_cat(NULL, addr->message);


       /* If the return code is > 128, it often means that a shell command
@@ -1119,7 +1115,7 @@ are complete before we pass this point. */


while (wait(&rc) >= 0);

-DEBUG(D_transport) debug_printf("%s transport yielded %d\n", tblock->name,
+DEBUG(D_transport) debug_printf("%s transport yielded %d\n", trname,
addr->transport_return);

/* If there has been a problem, the message in addr->message contains details
diff --git a/src/src/transports/pipe.h b/src/src/transports/pipe.h
index be5ec3424..569b675ad 100644
--- a/src/src/transports/pipe.h
+++ b/src/src/transports/pipe.h
@@ -46,7 +46,7 @@ extern pipe_transport_options_block pipe_transport_option_defaults;

/* The main and init entry points for the transport */

+extern void pipe_transport_init(driver_instance *);
extern BOOL pipe_transport_entry(transport_instance *, address_item *);
-extern void pipe_transport_init(transport_instance *);

/* End of transports/pipe.h */
diff --git a/src/src/transports/queuefile.c b/src/src/transports/queuefile.c
index 79020217b..2c35b3145 100644
--- a/src/src/transports/queuefile.c
+++ b/src/src/transports/queuefile.c
@@ -41,7 +41,7 @@ int queuefile_transport_options_count =

/* Dummy values */
queuefile_transport_options_block queuefile_transport_option_defaults = {0};
-void queuefile_transport_init(transport_instance *tblock) {}
+void queuefile_transport_init(driver_instance *tblock) {}
BOOL queuefile_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}

 #else   /*!MACRO_PREDEF*/
@@ -58,14 +58,14 @@ queuefile_transport_options_block queuefile_transport_option_defaults = {
 *          Initialization entry point            *
 *************************************************/


-void queuefile_transport_init(transport_instance *tblock)
+void queuefile_transport_init(driver_instance * t)
{
-queuefile_transport_options_block *ob =
- (queuefile_transport_options_block *) tblock->options_block;
+transport_instance * tblock = (transport_instance *)t;
+queuefile_transport_options_block * ob = t->options_block;

 if (!ob->dirname)
   log_write(0, LOG_PANIC_DIE | LOG_CONFIG,
-    "directory must be set for the %s transport", tblock->name);
+    "directory must be set for the %s transport", t->name);
 }


 /* This function will copy from a file to another
@@ -116,6 +116,7 @@ static BOOL
 copy_spool_files(transport_instance * tb, address_item * addr,
   const uschar * dstpath, int sdfd, int ddfd, BOOL link_file, int srcfd)
 {
+const uschar * trname = tb->drinst.name;
 BOOL is_hdr_file = srcfd < 0;
 const uschar * suffix = srcfd < 0 ? US"H" : US"D";
 int dstfd;
@@ -128,7 +129,7 @@ dstpath = string_sprintf("%s/%s-%s", dstpath, message_id, suffix);
 if (link_file)
   {
   DEBUG(D_transport) debug_printf("%s transport, linking %s => %s\n",
-    tb->name, srcpath, dstpath);
+    trname, srcpath, dstpath);


   if (linkat(sdfd, CCS filename, ddfd, CCS filename, 0) >= 0)
     return TRUE;
@@ -139,7 +140,7 @@ if (link_file)
 else                    /* use data copy */
   {
   DEBUG(D_transport) debug_printf("%s transport, copying %s => %s\n",
-    tb->name, srcpath, dstpath);
+    trname, srcpath, dstpath);


   if (  (s = dstpath,
      (dstfd = exim_openat4(ddfd, CCS filename, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE))
@@ -162,7 +163,7 @@ else                    /* use data copy */


addr->basic_errno = errno;
addr->message = string_sprintf("%s transport %s file: %s failed with error: %s",
- tb->name, op, s, strerror(errno));
+ trname, op, s, strerror(errno));
addr->transport_return = DEFER;
return FALSE;
}
@@ -177,8 +178,8 @@ the first address is the status for all addresses in a batch. */
BOOL
queuefile_transport_entry(transport_instance * tblock, address_item * addr)
{
-queuefile_transport_options_block * ob =
- (queuefile_transport_options_block *) tblock->options_block;
+queuefile_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
BOOL can_link;
uschar * sourcedir = spool_dname(US"input", message_subdir);
uschar * s, * dstdir;
@@ -186,7 +187,7 @@ struct stat dstatbuf, sstatbuf;
int ddfd = -1, sdfd = -1;

DEBUG(D_transport)
- debug_printf("%s transport entered\n", tblock->name);
+ debug_printf("%s transport entered\n", trname);

 #ifndef O_DIRECTORY
 # define O_DIRECTORY 0
@@ -199,7 +200,7 @@ GET_OPTION("directory");
 if (!(dstdir = expand_string(ob->dirname)))
   {
   addr->message = string_sprintf("%s transport: failed to expand dirname option",
-    tblock->name);
+    trname);
   addr->transport_return = DEFER;
   return FALSE;
   }
@@ -207,7 +208,7 @@ if (*dstdir != '/')
   {
   addr->transport_return = PANIC;
   addr->message = string_sprintf("%s transport directory: "
-    "%s is not absolute", tblock->name, dstdir);
+    "%s is not absolute", trname, dstdir);
   return FALSE;
   }


@@ -223,7 +224,7 @@ if (  (s = dstdir,
   addr->transport_return = PANIC;
   addr->basic_errno = errno;
   addr->message = string_sprintf("%s transport accessing directory: %s "
-    "failed with error: %s", tblock->name, s, strerror(errno));
+    "failed with error: %s", trname, s, strerror(errno));
   if (ddfd >= 0) (void) close(ddfd);
   return FALSE;
   }
@@ -235,7 +236,7 @@ if (  (s = dstdir,    fstat(ddfd, &dstatbuf) < 0)
   addr->transport_return = PANIC;
   addr->basic_errno = errno;
   addr->message = string_sprintf("%s transport fstat on directory fd: "
-    "%s failed with error: %s", tblock->name, s, strerror(errno));
+    "%s failed with error: %s", trname, s, strerror(errno));
   goto RETURN;
   }
 can_link = (dstatbuf.st_dev == sstatbuf.st_dev);
@@ -244,7 +245,7 @@ if (f.dont_deliver)
   {
   DEBUG(D_transport)
     debug_printf("*** delivery by %s transport bypassed by -N option\n",
-      tblock->name);
+      trname);
   addr->transport_return = OK;
   goto RETURN;
   }
@@ -252,26 +253,26 @@ if (f.dont_deliver)
 /* Link or copy the header and data spool files */


DEBUG(D_transport)
- debug_printf("%s transport, copying header file\n", tblock->name);
+ debug_printf("%s transport, copying header file\n", trname);

if (!copy_spool_files(tblock, addr, dstdir, sdfd, ddfd, can_link, -1))
goto RETURN;

DEBUG(D_transport)
- debug_printf("%s transport, copying data file\n", tblock->name);
+ debug_printf("%s transport, copying data file\n", trname);

 if (!copy_spool_files(tblock, addr, dstdir, sdfd, ddfd, can_link,
     deliver_datafile))
   {
   DEBUG(D_transport)
     debug_printf("%s transport, copying data file failed, "
-      "unlinking the header file\n", tblock->name);
+      "unlinking the header file\n", trname);
   Uunlink(string_sprintf("%s/%s-H", dstdir, message_id));
   goto RETURN;
   }


DEBUG(D_transport)
- debug_printf("%s transport succeeded\n", tblock->name);
+ debug_printf("%s transport succeeded\n", trname);

addr->transport_return = OK;

diff --git a/src/src/transports/queuefile.h b/src/src/transports/queuefile.h
index f5362515b..dfef4bd76 100644
--- a/src/src/transports/queuefile.h
+++ b/src/src/transports/queuefile.h
@@ -24,7 +24,7 @@ extern queuefile_transport_options_block queuefile_transport_option_defaults;

/* The main and init entry points for the transport */

+extern void queuefile_transport_init(driver_instance *);
extern BOOL queuefile_transport_entry(transport_instance *, address_item *);
-extern void queuefile_transport_init(transport_instance *);

/* End of transports/queuefile.h */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index f80afbc0a..f90ac16ba 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -159,7 +159,7 @@ int smtp_transport_options_count = nelem(smtp_transport_options);

/* Dummy values */
smtp_transport_options_block smtp_transport_option_defaults = {0};
-void smtp_transport_init(transport_instance *tblock) {}
+void smtp_transport_init(driver_instance *tblock) {}
BOOL smtp_transport_entry(transport_instance *tblock, address_item *addr) {return FALSE;}
void smtp_transport_closedown(transport_instance *tblock) {}

@@ -314,7 +314,7 @@ static int
smtp_transport_setup(transport_instance *tblock, address_item *addrlist,
transport_feedback *tf, uid_t uid, gid_t gid, uschar **errmsg)
{
-smtp_transport_options_block *ob = SOB tblock->options_block;
+smtp_transport_options_block * ob = tblock->drinst.options_block;

/* Pass back options if required. This interface is getting very messy. */

@@ -358,9 +358,10 @@ Returns:    nothing
 */


void
-smtp_transport_init(transport_instance *tblock)
+smtp_transport_init(driver_instance * t)
{
-smtp_transport_options_block * ob = SOB tblock->options_block;
+transport_instance * tblock = (transport_instance *)t;
+smtp_transport_options_block * ob = t->options_block;
int old_pool = store_pool;

 /* Retry_use_local_part defaults FALSE if unset */
@@ -387,7 +388,7 @@ if (ob->command_timeout <= 0 || ob->data_timeout <= 0 ||
     ob->final_timeout <= 0)
   log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
     "command, data, or final timeout value is zero for %s transport",
-      tblock->name);
+      t->name);


/* If hosts_override is set and there are local hosts, set the global
flag that stops verify from showing router hosts. */
@@ -672,8 +673,7 @@ deferred_event_raise(address_item * addr, host_item * host, uschar * evstr)
{
uschar * action = addr->transport->event_action;
const uschar * save_domain, * save_local;
-const uschar * save_rn;
-uschar * save_tn;
+const uschar * save_rn, * save_tn;

 if (!action)
   return;
@@ -689,7 +689,7 @@ deliver_host_port =    host->port == PORT_NONE ? 25 : host->port;
 event_defer_errno =    addr->basic_errno;


 router_name =    addr->router->drinst.name;
-transport_name = addr->transport->name;
+transport_name = addr->transport->drinst.name;
 deliver_domain = addr->domain;
 deliver_localpart = addr->local_part;


@@ -1836,6 +1836,7 @@ sender_address, helo_data and tls_certificate if enabled.
static uschar *
smtp_local_identity(const uschar * sender, struct transport_instance * tblock)
{
+smtp_transport_options_block * ob = tblock->drinst.options_block;
address_item * addr1;
uschar * if1 = US"";
uschar * helo1 = US"";
@@ -1844,7 +1845,6 @@ uschar * tlsc1 = US"";
#endif
const uschar * save_sender_address = sender_address;
uschar * local_identity = NULL;
-smtp_transport_options_block * ob = SOB tblock->options_block;

sender_address = sender;

@@ -1992,7 +1992,7 @@ static int
 smtp_chunk_cmd_callback(transport_ctx * tctx, unsigned chunk_size,
   unsigned flags)
 {
-smtp_transport_options_block * ob = SOB tctx->tblock->options_block;
+smtp_transport_options_block * ob = tctx->tblock->drinst.options_block;
 smtp_context * sx = tctx->smtp_context;
 int cmd_count = 0;
 int prev_cmd_count;
@@ -2140,7 +2140,7 @@ Returns:          OK    - the connection was made and the delivery attempted;
 int
 smtp_setup_conn(smtp_context * sx, BOOL suppress_tls)
 {
-smtp_transport_options_block * ob = sx->conn_args.tblock->options_block;
+smtp_transport_options_block * ob = sx->conn_args.tblock->drinst.options_block;
 BOOL pass_message = FALSE;
 uschar * message = NULL;
 int yield = OK;
@@ -3819,7 +3819,8 @@ smtp_deliver(address_item *addrlist, host_item *host, int host_af, int defport,
   uschar *interface, transport_instance *tblock,
   BOOL *message_defer, BOOL suppress_tls)
 {
-smtp_transport_options_block * ob = SOB tblock->options_block;
+smtp_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 int yield = OK;
 int save_errno;
 int rc;
@@ -3897,7 +3898,7 @@ if (tblock->filter_command)


   if (!transport_set_up_command(&transport_filter_argv,
     tblock->filter_command, TSUC_EXPAND_ARGS, DEFER, addrlist,
-    string_sprintf("%.50s transport filter", tblock->name), NULL))
+    string_sprintf("%.50s transport filter", trname), NULL))
     {
     set_errno_nohost(addrlist->next, addrlist->basic_errno, addrlist->message, DEFER,
       FALSE, &sx->delivery_start);
@@ -4156,7 +4157,7 @@ else
        )
         &&
 #endif
-           transport_check_waiting(tblock->name, host->name,
+           transport_check_waiting(trname, host->name,
              tblock->connection_max_messages, continue_next_id,
          (oicf)smtp_are_same_identities, (void*)&t_compare);
     if (!tcw)
@@ -4428,7 +4429,7 @@ else
         write error, as it may prove possible to update the spool file later. */


         if (testflag(addr, af_homonym))
-          sprintf(CS sx->buffer, "%.500s/%s\n", addr->unique + 3, tblock->name);
+          sprintf(CS sx->buffer, "%.500s/%s\n", addr->unique + 3, trname);
         else
           sprintf(CS sx->buffer, "%.500s\n", addr->unique);


@@ -4475,7 +4476,7 @@ else
     if (addr->transport_return == OK)
       {
       if (testflag(addr, af_homonym))
-        sprintf(CS sx->buffer, "%.500s/%s\n", addr->unique + 3, tblock->name);
+        sprintf(CS sx->buffer, "%.500s/%s\n", addr->unique + 3, trname);
       else
         sprintf(CS sx->buffer, "%.500s\n", addr->unique);


@@ -4745,7 +4746,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
          )
       &&
 #endif
-         transport_check_waiting(tblock->name, host->name,
+         transport_check_waiting(trname, host->name,
            sx->max_mail, continue_next_id,
            (oicf)smtp_are_same_identities, (void*)&t_compare)
        )  )
@@ -5077,9 +5078,9 @@ Returns:    nothing
 */


 void
-smtp_transport_closedown(transport_instance *tblock)
+smtp_transport_closedown(transport_instance * tblock)
 {
-smtp_transport_options_block * ob = SOB tblock->options_block;
+smtp_transport_options_block * ob = tblock->drinst.options_block;
 client_conn_ctx cctx;
 smtp_context sx = {0};
 uschar buffer[256];
@@ -5173,18 +5174,19 @@ smtp_transport_entry(
   transport_instance * tblock,      /* data for this instantiation */
   address_item * addrlist)          /* addresses we are working on */
 {
+smtp_transport_options_block * ob = tblock->drinst.options_block;
+const uschar * trname = tblock->drinst.name;
 int defport;
 int hosts_defer = 0, hosts_fail  = 0, hosts_looked_up = 0;
 int hosts_retry = 0, hosts_serial = 0, hosts_total = 0, total_hosts_tried = 0;
 BOOL expired = TRUE;
 uschar * expanded_hosts = NULL, * pistring;
-uschar * tid = string_sprintf("%s transport", tblock->name);
-smtp_transport_options_block * ob = SOB tblock->options_block;
+uschar * tid = string_sprintf("%s transport", trname);
 host_item * hostlist = addrlist->host_list, * host = NULL;


 DEBUG(D_transport)
   {
-  debug_printf("%s transport entered\n", tblock->name);
+  debug_printf("%s transport entered\n", trname);
   for (address_item * addr = addrlist; addr; addr = addr->next)
     debug_printf("  %s\n", addr->address);
   if (hostlist)
@@ -5232,7 +5234,7 @@ if (!hostlist || (ob->hosts_override && ob->hosts))
   if (!ob->hosts)
     {
     addrlist->message = string_sprintf("%s transport called with no hosts set",
-      tblock->name);
+      trname);
     addrlist->transport_return = PANIC;
     return FALSE;   /* Only top address has status */
     }
@@ -5257,7 +5259,7 @@ if (!hostlist || (ob->hosts_override && ob->hosts))
       if (!(expanded_hosts = expand_string(s)))
         {
         addrlist->message = string_sprintf("failed to expand list of hosts "
-          "\"%s\" in %s transport: %s", s, tblock->name, expand_string_message);
+          "\"%s\" in %s transport: %s", s, trname, expand_string_message);
         addrlist->transport_return = f.search_find_defer ? DEFER : PANIC;
         return FALSE;     /* Only top address has status */
         }
@@ -5272,7 +5274,7 @@ if (!hostlist || (ob->hosts_override && ob->hosts))
       {
       log_write(0, LOG_MAIN|LOG_PANIC,
     "attempt to use tainted host list '%s' from '%s' in transport %s",
-    s, ob->hosts, tblock->name);
+    s, ob->hosts, trname);
       /* Avoid leaking info to an attacker */
       addrlist->message = US"internal configuration error";
       addrlist->transport_return = PANIC;
@@ -5285,7 +5287,7 @@ if (!hostlist || (ob->hosts_override && ob->hosts))
     if (!hostlist)
       {
       addrlist->message =
-        string_sprintf("%s transport has empty hosts setting", tblock->name);
+        string_sprintf("%s transport has empty hosts setting", trname);
       addrlist->transport_return = PANIC;
       return FALSE;   /* Only top address has status */
       }
@@ -5527,7 +5529,7 @@ retry_non_continued:
           {
           addr->basic_errno = ERRNO_HOST_IS_LOCAL;
           addr->message = string_sprintf("%s transport found host %s to be "
-            "local", tblock->name, host->name);
+            "local", trname, host->name);
           }
         goto END_TRANSPORT;
         }
@@ -5657,7 +5659,7 @@ retry_non_continued:
       If either of these retry records are actually read, the keys used are
       returned to save recomputing them later. */


-      if (exp_bool(addrlist, US"transport", tblock->name, D_transport,
+      if (exp_bool(addrlist, US"transport", trname, D_transport,
         US"retry_include_ip_address", ob->retry_include_ip_address,
         ob->expand_retry_include_ip_address, &incl_ip) != OK)
     continue;    /* with next host */
@@ -5780,7 +5782,7 @@ retry_non_continued:
       DEBUG(D_transport)
         {
         debug_printf("*** delivery by %s transport bypassed by -N option\n"
-                     "*** host and remaining hosts:\n", tblock->name);
+                     "*** host and remaining hosts:\n", trname);
         for (host_item * host2 = host; host2; host2 = host2->next)
           debug_printf("    %s [%s]\n", host2->name,
             host2->address ? host2->address : US"unset");
@@ -5929,7 +5931,7 @@ retry_non_continued:
       if (!retry_host_key)
         {
     BOOL incl_ip;
-    if (exp_bool(addrlist, US"transport", tblock->name, D_transport,
+    if (exp_bool(addrlist, US"transport", trname, D_transport,
           US"retry_include_ip_address", ob->retry_include_ip_address,
           ob->expand_retry_include_ip_address, &incl_ip) != OK)
       incl_ip = TRUE;    /* error; use most-specific retry record */
@@ -5975,7 +5977,7 @@ retry_non_continued:
       if (!retry_message_key)
         {
     BOOL incl_ip;
-    if (exp_bool(addrlist, US"transport", tblock->name, D_transport,
+    if (exp_bool(addrlist, US"transport", trname, D_transport,
           US"retry_include_ip_address", ob->retry_include_ip_address,
           ob->expand_retry_include_ip_address, &incl_ip) != OK)
       incl_ip = TRUE;    /* error; use most-specific retry record */
@@ -6212,11 +6214,11 @@ per connection then follow-on deliveries are not possible and there's no need
 to create/update the per-transport wait-<transport_name> database. */


if (update_waiting && tblock->connection_max_messages != 1)
- transport_update_waiting(hostlist, tblock->name);
+ transport_update_waiting(hostlist, trname);

END_TRANSPORT:

-DEBUG(D_transport) debug_printf("Leaving %s transport\n", tblock->name);
+DEBUG(D_transport) debug_printf("Leaving %s transport\n", trname);

return TRUE; /* Each address has its status */
}
diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h
index 1d892d567..9fc95444b 100644
--- a/src/src/transports/smtp.h
+++ b/src/src/transports/smtp.h
@@ -240,8 +240,8 @@ extern smtp_transport_options_block smtp_transport_option_defaults;

/* The main, init, and closedown entry points for the transport */

+extern void smtp_transport_init(driver_instance *);
extern BOOL smtp_transport_entry(transport_instance *, address_item *);
-extern void smtp_transport_init(transport_instance *);
extern void smtp_transport_closedown(transport_instance *);


diff --git a/src/src/transports/smtp_socks.c b/src/src/transports/smtp_socks.c
index 8848dd7a5..a626a00d3 100644
--- a/src/src/transports/smtp_socks.c
+++ b/src/src/transports/smtp_socks.c
@@ -211,10 +211,8 @@ int
 socks_sock_connect(host_item * host, int host_af, int port, uschar * interface,
   transport_instance * tb, int timeout)
 {
-smtp_transport_options_block * ob =
-  (smtp_transport_options_block *)tb->options_block;
-const uschar * proxy_list;
-const uschar * proxy_spec;
+smtp_transport_options_block * ob = tb->drinst.options_block;
+const uschar * proxy_list, * proxy_spec;
 int sep = 0;
 int fd;
 time_t tmo;
@@ -233,7 +231,7 @@ GET_OPTION("socks_proxy");
 if (!(proxy_list = expand_string(ob->socks_proxy)))
   {
   log_write(0, LOG_MAIN|LOG_PANIC, "Bad expansion for socks_proxy in %s",
-    tb->name);
+    tb->drinst.name);
   return -1;
   }


diff --git a/src/src/verify.c b/src/src/verify.c
index ad6b0afaf..3f3071223 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -364,7 +364,7 @@ if (addr->transport == cutthrough.addr.transport)
       deliver_host_address = host->address;
       deliver_host_port = host->port;
       deliver_domain = addr->domain;
-      transport_name = addr->transport->name;
+      transport_name = addr->transport->drinst.name;


       host_af = Ustrchr(host->address, ':') ? AF_INET6 : AF_INET;


@@ -565,13 +565,12 @@ if (!addr->transport)
HDEBUG(D_verify) debug_printf("cannot callout via null transport\n");
}

-else if (Ustrcmp(addr->transport->driver_name, "smtp") != 0)
+else if (Ustrcmp(addr->transport->drinst.driver_name, "smtp") != 0)
   log_write(0, LOG_MAIN|LOG_PANIC|LOG_CONFIG_FOR, "callout transport '%s': %s is non-smtp",
-    addr->transport->name, addr->transport->driver_name);
+    addr->transport->drinst.name, addr->transport->drinst.driver_name);
 else
   {
-  smtp_transport_options_block *ob =
-    (smtp_transport_options_block *)addr->transport->options_block;
+  smtp_transport_options_block * ob = addr->transport->drinst.options_block;
   smtp_context * sx = NULL;


   /* The information wasn't available in the cache, so we have to do a real
@@ -663,7 +662,7 @@ coding means skipping this whole loop and doing the append separately.  */
     deliver_host_address = host->address;
     deliver_host_port = host->port;
     deliver_domain = addr->domain;
-    transport_name = addr->transport->name;
+    transport_name = addr->transport->drinst.name;


     GET_OPTION("interface");
     if (  !smtp_get_interface(tf->interface, host_af, addr, &interface,
@@ -1127,7 +1126,7 @@ no_conn:
       /* We assume no buffer in use in the outblock */
       cutthrough.cctx =        sx->cctx;
       cutthrough.nrcpt =    1;
-      cutthrough.transport =    addr->transport->name;
+      cutthrough.transport =    addr->transport->drinst.name;
       cutthrough.interface =    interface;
       cutthrough.snd_port =    sending_port;
       cutthrough.peer_options =    smtp_peer_options;
@@ -1853,7 +1852,7 @@ while (addr_new)
         fprintf(fp, "\n*** Error in setting up pipe, file, or autoreply:\n"
           "%s\n", addr->message);
       else if (allow)
-        fprintf(fp, "\n  transport = %s\n", addr->transport->name);
+        fprintf(fp, "\n  transport = %s\n", addr->transport->drinst.name);
       else
         fprintf(fp, " *** forbidden ***\n");
       }
@@ -1916,7 +1915,9 @@ while (addr_new)
       sending a message to this address. */


       if ((tp = addr->transport))
-    if (!tp->info->local)
+    {
+    transport_info * ti = tp->drinst.info;
+    if (!ti->local)
       {
       (void)(tp->setup)(tp, addr, &tf, 0, 0, NULL);


@@ -1942,7 +1943,7 @@ while (addr_new)
           {
           log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand list of hosts "
         "\"%s\" in %s transport for callout: %s", tf.hosts,
-        tp->name, expand_string_message);
+        tp->drinst.name, expand_string_message);
           }
         else
           {
@@ -1968,10 +1969,9 @@ while (addr_new)
         else
           {
           const dnssec_domains * dsp = NULL;
-          if (Ustrcmp(tp->driver_name, "smtp") == 0)
+          if (Ustrcmp(tp->drinst.driver_name, "smtp") == 0)
             {
-            smtp_transport_options_block * ob =
-            (smtp_transport_options_block *) tp->options_block;
+            smtp_transport_options_block * ob = tp->drinst.options_block;
             dsp = &ob->dnssec;
             }


@@ -1983,8 +1983,9 @@ while (addr_new)
         }
       }
     else if (  options & vopt_quota
-        && Ustrcmp(tp->driver_name, "appendfile") == 0)
+        && Ustrcmp(tp->drinst.driver_name, "appendfile") == 0)
       local_verify = TRUE;
+    }


       /* Can only do a callout if we have at least one host! If the callout
       fails, it will have set ${sender,recipient}_verify_failure. */
@@ -2235,13 +2236,14 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
     /* Show router, and transport */


     fprintf(fp, "router = %s, transport = %s\n",
-      addr->router->drinst.name, tp ? tp->name : US"unset");
+      addr->router->drinst.name, tp ? tp->drinst.name : US"unset");


     /* Show any hosts that are set up by a router unless the transport
     is going to override them; fiddle a bit to get a nice format. */


     if (addr->host_list && tp && !tp->overrides_hosts)
       {
+      transport_info * ti = tp->drinst.info;
       int maxlen = 0;
       int maxaddlen = 0;
       for (host_item * h = addr->host_list; h; h = h->next)
@@ -2257,7 +2259,7 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)


     if (h->address)
       fprintf(fp, "[%s%-*c", h->address, maxaddlen+1 - Ustrlen(h->address), ']');
-    else if (tp->info->local)
+    else if (ti->local)
       fprintf(fp, " %-*s ", maxaddlen, "");  /* Omit [unknown] for local */
     else
       fprintf(fp, "[%s%-*c", "unknown", maxaddlen+1 - 7, ']');


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/