Make $smtp_command_argument available for all SMTP commands.
[exim.git] / src / src / smtp_in.c
index 6e62b99e0fb1ce237cc6237058ea9e8f69aa768f..f6a2af89c94671108eb27623f665406d27f7b29d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.17 2005/04/27 13:29:32 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.23 2005/08/22 14:01:37 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -119,8 +119,6 @@ static int  unknown_command_count;
 static int  sync_cmd_limit;
 static int  smtp_write_error = 0;
 
-static uschar *smtp_data;
-
 static uschar *cmd_buffer;
 
 /* We need to know the position of RSET, HELO, EHLO, AUTH, and STARTTLS. Their
@@ -535,7 +533,7 @@ for (p = cmd_list; p < cmd_list_end; p++)
     the following test, so that if it fails, the command name can easily be
     logged. */
 
-    smtp_data = cmd_buffer + p->len;
+    smtp_command_argument = cmd_buffer + p->len;
 
     /* Count non-mail commands from those hosts that are controlled in this
     way. The default is all hosts. We don't waste effort checking the list
@@ -553,11 +551,11 @@ for (p = cmd_list; p < cmd_list_end; p++)
         return TOO_MANY_NONMAIL_CMD;
       }
 
-    /* Get the data pointer over leading spaces and return; if there is no data
-    for a command that expects it, we give the error centrally here. */
+    /* Get the data pointer over leading spaces and return; if there is data
+    for a command that does not expect it, give the error centrally here. */
 
-    while (isspace(*smtp_data)) smtp_data++;
-    return (p->has_arg || *smtp_data == 0)? p->cmd : BADARG_CMD;
+    while (isspace(*smtp_command_argument)) smtp_command_argument++;
+    return (p->has_arg || *smtp_command_argument == 0)? p->cmd : BADARG_CMD;
     }
   }
 
@@ -745,7 +743,7 @@ return yield;
 *         Extract SMTP command option            *
 *************************************************/
 
-/* This function picks the next option setting off the end of smtp_data. It
+/* This function picks the next option setting off the end of smtp_command_argument. It
 is called for MAIL FROM and RCPT TO commands, to pick off the optional ESMTP
 things that can appear there.
 
@@ -760,11 +758,11 @@ static BOOL
 extract_option(uschar **name, uschar **value)
 {
 uschar *n;
-uschar *v = smtp_data + Ustrlen(smtp_data) -1;
+uschar *v = smtp_command_argument + Ustrlen(smtp_command_argument) -1;
 while (isspace(*v)) v--;
 v[1] = 0;
 
-while (v > smtp_data && *v != '=' && !isspace(*v)) v--;
+while (v > smtp_command_argument && *v != '=' && !isspace(*v)) v--;
 if (*v != '=') return FALSE;
 
 n = v;
@@ -809,7 +807,7 @@ message_size = -1;
 acl_warn_headers = NULL;
 queue_only_policy = FALSE;
 deliver_freeze = FALSE;                              /* Can be set by ACL */
-fake_reject = FALSE;                                 /* Can be set by ACL */
+fake_response = OK;                                  /* Can be set by ACL */
 #ifdef WITH_CONTENT_SCAN
 no_mbox_unspool = FALSE;                             /* Can be set by ACL */
 #endif
@@ -838,6 +836,10 @@ spf_smtp_comment = NULL;
 #endif
 body_linecount = body_zerocount = 0;
 
+sender_rate = sender_rate_limit = sender_rate_period = NULL;
+ratelimiters_mail = NULL;           /* Updated by ratelimit ACL condition */
+                   /* Note that ratelimiters_conn persists across resets. */
+
 for (i = 0; i < ACL_M_MAX; i++) acl_var[ACL_C_MAX + i] = NULL;
 
 /* The message body variables use malloc store. They may be set if this is
@@ -922,7 +924,7 @@ while (done <= 0)
     case HELO_CMD:
     case EHLO_CMD:
 
-    check_helo(smtp_data);
+    check_helo(smtp_command_argument);
     /* Fall through */
 
     case RSET_CMD:
@@ -942,7 +944,7 @@ while (done <= 0)
       /* The function moan_smtp_batch() does not return. */
       moan_smtp_batch(cmd_buffer, "503 Sender already given");
 
-    if (smtp_data[0] == 0)
+    if (smtp_command_argument[0] == 0)
       /* The function moan_smtp_batch() does not return. */
       moan_smtp_batch(cmd_buffer, "501 MAIL FROM must have an address operand");
 
@@ -953,8 +955,8 @@ while (done <= 0)
     /* Apply SMTP rewrite */
 
     raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)?
-      rewrite_one(smtp_data, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE,
-        US"", global_rewrite_rules) : smtp_data;
+      rewrite_one(smtp_command_argument, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE,
+        US"", global_rewrite_rules) : smtp_command_argument;
 
     /* Extract the address; the TRUE flag allows <> as valid */
 
@@ -997,7 +999,7 @@ while (done <= 0)
       /* The function moan_smtp_batch() does not return. */
       moan_smtp_batch(cmd_buffer, "503 No sender yet given");
 
-    if (smtp_data[0] == 0)
+    if (smtp_command_argument[0] == 0)
       /* The function moan_smtp_batch() does not return. */
       moan_smtp_batch(cmd_buffer, "501 RCPT TO must have an address operand");
 
@@ -1012,8 +1014,8 @@ while (done <= 0)
     recipient address */
 
     recipient = ((rewrite_existflags & rewrite_smtp) != 0)?
-      rewrite_one(smtp_data, rewrite_smtp, NULL, FALSE, US"",
-        global_rewrite_rules) : smtp_data;
+      rewrite_one(smtp_command_argument, rewrite_smtp, NULL, FALSE, US"",
+        global_rewrite_rules) : smtp_command_argument;
 
     /* rfc821_domains = TRUE; << no longer needed */
     recipient = parse_extract_address(recipient, &errmess, &start, &end,
@@ -1542,8 +1544,7 @@ if (acl_smtp_connect != NULL)
   {
   int rc;
   uschar *user_msg, *log_msg;
-  smtp_data = US"in \"connect\" ACL";    /* For logged failure message */
-  rc = acl_check(ACL_WHERE_CONNECT, US"", acl_smtp_connect, &user_msg,
+  rc = acl_check(ACL_WHERE_CONNECT, NULL, acl_smtp_connect, &user_msg,
     &log_msg);
   if (rc != OK)
     {
@@ -1621,7 +1622,7 @@ if (smtp_enforce_sync && sender_host_address != NULL && !sender_host_notsocket)
       {
       if (rc > 150) rc = 150;
       smtp_inbuffer[rc] = 0;
-      log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: "
+      log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol "
         "synchronization error (input sent without waiting for greeting): "
         "rejected connection from %s input=\"%s\"", host_and_ident(TRUE),
         string_printing(smtp_inbuffer));
@@ -1812,12 +1813,15 @@ int code = acl_wherecodes[where];
 BOOL drop = rc == FAIL_DROP;
 uschar *lognl;
 uschar *sender_info = US"";
-uschar *what = (where == ACL_WHERE_PREDATA)? US"DATA" :
+uschar *what =
 #ifdef WITH_CONTENT_SCAN
-               (where == ACL_WHERE_MIME)? US"during MIME ACL checks" :
+  (where == ACL_WHERE_MIME)? US"during MIME ACL checks" :
 #endif
-               (where == ACL_WHERE_DATA)? US"after DATA" :
-  string_sprintf("%s %s", acl_wherenames[where], smtp_data);
+  (where == ACL_WHERE_PREDATA)? US"DATA" :
+  (where == ACL_WHERE_DATA)? US"after DATA" :
+  (smtp_command_argument == NULL)?
+    string_sprintf("%s in \"connect\" ACL", acl_wherenames[where]) :
+    string_sprintf("%s %s", acl_wherenames[where], smtp_command_argument);
 
 if (drop) rc = FAIL;
 
@@ -1928,6 +1932,130 @@ return 2;
 
 
 
+/*************************************************
+*             Verify HELO argument               *
+*************************************************/
+
+/* This function is called if helo_verify_hosts or helo_try_verify_hosts is
+matched. It is also called from ACL processing if verify = helo is used and
+verification was not previously tried (i.e. helo_try_verify_hosts was not
+matched). The result of its processing is to set helo_verified and
+helo_verify_failed. These variables should both be FALSE for this function to
+be called.
+
+Note that EHLO/HELO is legitimately allowed to quote an address literal. Allow
+for IPv6 ::ffff: literals.
+
+Argument:   none
+Returns:    TRUE if testing was completed;
+            FALSE on a temporary failure
+*/
+
+BOOL
+smtp_verify_helo(void)
+{
+BOOL yield = TRUE;
+
+HDEBUG(D_receive) debug_printf("verifying EHLO/HELO argument \"%s\"\n",
+  sender_helo_name);
+
+if (sender_helo_name == NULL)
+  {
+  HDEBUG(D_receive) debug_printf("no EHLO/HELO command was issued\n");
+  }
+
+else if (sender_helo_name[0] == '[')
+  {
+  helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address,
+    Ustrlen(sender_host_address)) == 0;
+
+  #if HAVE_IPV6
+  if (!helo_verified)
+    {
+    if (strncmpic(sender_host_address, US"::ffff:", 7) == 0)
+      helo_verified = Ustrncmp(sender_helo_name + 1,
+        sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0;
+    }
+  #endif
+
+  HDEBUG(D_receive)
+    { if (helo_verified) debug_printf("matched host address\n"); }
+  }
+
+/* Do a reverse lookup if one hasn't already given a positive or negative
+response. If that fails, or the name doesn't match, try checking with a forward
+lookup. */
+
+else
+  {
+  if (sender_host_name == NULL && !host_lookup_failed)
+    yield = host_name_lookup() != DEFER;
+
+  /* If a host name is known, check it and all its aliases. */
+
+  if (sender_host_name != NULL)
+    {
+    helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0;
+
+    if (helo_verified)
+      {
+      HDEBUG(D_receive) debug_printf("matched host name\n");
+      }
+    else
+      {
+      uschar **aliases = sender_host_aliases;
+      while (*aliases != NULL)
+        {
+        helo_verified = strcmpic(*aliases++, sender_helo_name) == 0;
+        if (helo_verified) break;
+        }
+      HDEBUG(D_receive)
+        {
+        if (helo_verified)
+          debug_printf("matched alias %s\n", *(--aliases));
+        }
+      }
+    }
+
+  /* Final attempt: try a forward lookup of the helo name */
+
+  if (!helo_verified)
+    {
+    int rc;
+    host_item h;
+    h.name = sender_helo_name;
+    h.address = NULL;
+    h.mx = MX_NONE;
+    h.next = NULL;
+    HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
+      sender_helo_name);
+    rc = host_find_byname(&h, NULL, NULL, TRUE);
+    if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
+      {
+      host_item *hh = &h;
+      while (hh != NULL)
+        {
+        if (Ustrcmp(hh->address, sender_host_address) == 0)
+          {
+          helo_verified = TRUE;
+          HDEBUG(D_receive)
+            debug_printf("IP address for %s matches calling address\n",
+              sender_helo_name);
+          break;
+          }
+        hh = hh->next;
+        }
+      }
+    }
+  }
+
+if (!helo_verified) helo_verify_failed = FALSE;  /* We've tried ... */
+return yield;
+}
+
+
+
+
 /*************************************************
 *       Initialize for SMTP incoming message     *
 *************************************************/
@@ -2051,8 +2179,7 @@ while (done <= 0)
 
     if (acl_smtp_auth != NULL)
       {
-      rc = acl_check(ACL_WHERE_AUTH, smtp_data, acl_smtp_auth, &user_msg,
-        &log_msg);
+      rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg);
       if (rc != OK)
         {
         done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
@@ -2062,8 +2189,8 @@ while (done <= 0)
 
     /* Find the name of the requested authentication mechanism. */
 
-    s = smtp_data;
-    while ((c = *smtp_data) != 0 && !isspace(c))
+    s = smtp_command_argument;
+    while ((c = *smtp_command_argument) != 0 && !isspace(c))
       {
       if (!isalnum(c) && c != '-' && c != '_')
         {
@@ -2071,16 +2198,16 @@ while (done <= 0)
           US"invalid character in authentication mechanism name");
         goto COMMAND_LOOP;
         }
-      smtp_data++;
+      smtp_command_argument++;
       }
 
     /* If not at the end of the line, we must be at white space. Terminate the
     name and move the pointer on to any data that may be present. */
 
-    if (*smtp_data != 0)
+    if (*smtp_command_argument != 0)
       {
-      *smtp_data++ = 0;
-      while (isspace(*smtp_data)) smtp_data++;
+      *smtp_command_argument++ = 0;
+      while (isspace(*smtp_command_argument)) smtp_command_argument++;
       }
 
     /* Search for an authentication mechanism which is configured for use
@@ -2110,7 +2237,7 @@ while (done <= 0)
     expand_nmax = 0;
     expand_nlength[0] = 0;   /* $0 contains nothing */
 
-    c = (au->info->servercode)(au, smtp_data);
+    c = (au->info->servercode)(au, smtp_command_argument);
     if (au->set_id != NULL) set_id = expand_string(au->set_id);
     expand_nmax = -1;        /* Reset numeric variables */
 
@@ -2226,14 +2353,14 @@ while (done <= 0)
     /* Reject the HELO if its argument was invalid or non-existent. A
     successful check causes the argument to be saved in malloc store. */
 
-    if (!check_helo(smtp_data))
+    if (!check_helo(smtp_command_argument))
       {
       smtp_printf("501 Syntactically invalid %s argument(s)\r\n", hello);
 
       log_write(0, LOG_MAIN|LOG_REJECT, "rejected %s from %s: syntactically "
         "invalid argument(s): %s", hello, host_and_ident(FALSE),
-        (*smtp_data == 0)? US"(no argument given)" :
-                           string_printing(smtp_data));
+        (*smtp_command_argument == 0)? US"(no argument given)" :
+                           string_printing(smtp_command_argument));
 
       if (++synprot_error_count > smtp_max_synprot_errors)
         {
@@ -2256,7 +2383,7 @@ while (done <= 0)
     if (!sender_host_unknown)
       {
       BOOL old_helo_verified = helo_verified;
-      uschar *p = smtp_data;
+      uschar *p = smtp_command_argument;
 
       while (*p != 0 && !isspace(*p)) { *p = tolower(*p); p++; }
       *p = 0;
@@ -2278,104 +2405,16 @@ while (done <= 0)
         (tls_active >= 0)? " TLS" : "", host_and_ident(FALSE));
 
       /* Verify if configured. This doesn't give much security, but it does
-      make some people happy to be able to do it. Note that HELO is legitimately
-      allowed to quote an address literal. Allow for IPv6 ::ffff: literals. */
+      make some people happy to be able to do it. If helo_required is set,
+      (host matches helo_verify_hosts) failure forces rejection. If helo_verify
+      is set (host matches helo_try_verify_hosts), it does not. This is perhaps
+      now obsolescent, since the verification can now be requested selectively
+      at ACL time. */
 
-      helo_verified = FALSE;
+      helo_verified = helo_verify_failed = FALSE;
       if (helo_required || helo_verify)
         {
-        BOOL tempfail = FALSE;
-
-        HDEBUG(D_receive) debug_printf("verifying %s %s\n", hello,
-          sender_helo_name);
-        if (sender_helo_name[0] == '[')
-          {
-          helo_verified = Ustrncmp(sender_helo_name+1, sender_host_address,
-            Ustrlen(sender_host_address)) == 0;
-
-          #if HAVE_IPV6
-          if (!helo_verified)
-            {
-            if (strncmpic(sender_host_address, US"::ffff:", 7) == 0)
-              helo_verified = Ustrncmp(sender_helo_name + 1,
-                sender_host_address + 7, Ustrlen(sender_host_address) - 7) == 0;
-            }
-          #endif
-
-          HDEBUG(D_receive)
-            { if (helo_verified) debug_printf("matched host address\n"); }
-          }
-
-        /* Do a reverse lookup if one hasn't already given a positive or
-        negative response. If that fails, or the name doesn't match, try
-        checking with a forward lookup. */
-
-        else
-          {
-          if (sender_host_name == NULL && !host_lookup_failed)
-            tempfail = host_name_lookup() == DEFER;
-
-          /* If a host name is known, check it and all its aliases. */
-
-          if (sender_host_name != NULL)
-            {
-            helo_verified = strcmpic(sender_host_name, sender_helo_name) == 0;
-
-            if (helo_verified)
-              {
-              HDEBUG(D_receive) debug_printf("matched host name\n");
-              }
-            else
-              {
-              uschar **aliases = sender_host_aliases;
-              while (*aliases != NULL)
-                {
-                helo_verified = strcmpic(*aliases++, sender_helo_name) == 0;
-                if (helo_verified) break;
-                }
-              HDEBUG(D_receive)
-                {
-                if (helo_verified)
-                  debug_printf("matched alias %s\n", *(--aliases));
-                }
-              }
-            }
-
-          /* Final attempt: try a forward lookup of the helo name */
-
-          if (!helo_verified)
-            {
-            int rc;
-            host_item h;
-            h.name = sender_helo_name;
-            h.address = NULL;
-            h.mx = MX_NONE;
-            h.next = NULL;
-            HDEBUG(D_receive) debug_printf("getting IP address for %s\n",
-              sender_helo_name);
-            rc = host_find_byname(&h, NULL, NULL, TRUE);
-            if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL)
-              {
-              host_item *hh = &h;
-              while (hh != NULL)
-                {
-                if (Ustrcmp(hh->address, sender_host_address) == 0)
-                  {
-                  helo_verified = TRUE;
-                  HDEBUG(D_receive)
-                    debug_printf("IP address for %s matches calling address\n",
-                      sender_helo_name);
-                  break;
-                  }
-                hh = hh->next;
-                }
-              }
-            }
-          }
-
-        /* Verification failed. A temporary lookup failure gives a temporary
-        error. */
-
+        BOOL tempfail = !smtp_verify_helo();
         if (!helo_verified)
           {
           if (helo_required)
@@ -2403,8 +2442,7 @@ while (done <= 0)
 
     if (acl_smtp_helo != NULL)
       {
-      rc = acl_check(ACL_WHERE_HELO, smtp_data, acl_smtp_helo, &user_msg,
-        &log_msg);
+      rc = acl_check(ACL_WHERE_HELO, NULL, acl_smtp_helo, &user_msg, &log_msg);
       if (rc != OK)
         {
         done = smtp_handle_acl_fail(ACL_WHERE_HELO, rc, user_msg, log_msg);
@@ -2589,7 +2627,7 @@ while (done <= 0)
     if (tls_active >= 0) (void)tls_write(s, ptr); else
     #endif
 
-    fwrite(s, 1, ptr, smtp_out);
+    (void)fwrite(s, 1, ptr, smtp_out);
     DEBUG(D_receive) debug_printf("SMTP>> %s", s);
     helo_seen = TRUE;
     break;   /* HELO/EHLO */
@@ -2620,7 +2658,7 @@ while (done <= 0)
       break;
       }
 
-    if (smtp_data[0] == 0)
+    if (smtp_command_argument[0] == 0)
       {
       done = synprot_error(L_smtp_protocol_error, 501, NULL,
         US"MAIL must have an address operand");
@@ -2779,8 +2817,8 @@ while (done <= 0)
     TRUE flag allows "<>" as a sender address. */
 
     raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)?
-      rewrite_one(smtp_data, rewrite_smtp, NULL, FALSE, US"",
-        global_rewrite_rules) : smtp_data;
+      rewrite_one(smtp_command_argument, rewrite_smtp, NULL, FALSE, US"",
+        global_rewrite_rules) : smtp_command_argument;
 
     /* rfc821_domains = TRUE; << no longer needed */
     raw_sender =
@@ -2790,7 +2828,7 @@ while (done <= 0)
 
     if (raw_sender == NULL)
       {
-      done = synprot_error(L_smtp_syntax_error, 501, smtp_data, errmess);
+      done = synprot_error(L_smtp_syntax_error, 501, smtp_command_argument, errmess);
       break;
       }
 
@@ -2850,7 +2888,7 @@ while (done <= 0)
       else
         {
         smtp_printf("501 %s: sender address must contain a domain\r\n",
-          smtp_data);
+          smtp_command_argument);
         log_write(L_smtp_syntax_error,
           LOG_MAIN|LOG_REJECT,
           "unqualified sender rejected: <%s> %s%s",
@@ -2918,7 +2956,7 @@ while (done <= 0)
 
     /* Check for an operand */
 
-    if (smtp_data[0] == 0)
+    if (smtp_command_argument[0] == 0)
       {
       done = synprot_error(L_smtp_syntax_error, 501, NULL,
         US"RCPT must have an address operand");
@@ -2930,8 +2968,8 @@ while (done <= 0)
     as a recipient address */
 
     recipient = ((rewrite_existflags & rewrite_smtp) != 0)?
-      rewrite_one(smtp_data, rewrite_smtp, NULL, FALSE, US"",
-        global_rewrite_rules) : smtp_data;
+      rewrite_one(smtp_command_argument, rewrite_smtp, NULL, FALSE, US"",
+        global_rewrite_rules) : smtp_command_argument;
 
     /* rfc821_domains = TRUE; << no longer needed */
     recipient = parse_extract_address(recipient, &errmess, &start, &end,
@@ -2940,7 +2978,7 @@ while (done <= 0)
 
     if (recipient == NULL)
       {
-      done = synprot_error(L_smtp_syntax_error, 501, smtp_data, errmess);
+      done = synprot_error(L_smtp_syntax_error, 501, smtp_command_argument, errmess);
       rcpt_fail_count++;
       break;
       }
@@ -2970,7 +3008,7 @@ while (done <= 0)
         {
         rcpt_fail_count++;
         smtp_printf("501 %s: recipient address must contain a domain\r\n",
-          smtp_data);
+          smtp_command_argument);
         log_write(L_smtp_syntax_error,
           LOG_MAIN|LOG_REJECT, "unqualified recipient rejected: "
           "<%s> %s%s", recipient, host_and_ident(TRUE),
@@ -3044,7 +3082,7 @@ while (done <= 0)
         "discarded by %s ACL%s%s", host_and_ident(TRUE),
         (sender_address_unrewritten != NULL)?
         sender_address_unrewritten : sender_address,
-        smtp_data, recipients_discarded? "MAIL" : "RCPT",
+        smtp_command_argument, recipients_discarded? "MAIL" : "RCPT",
         (log_msg == NULL)? US"" : US": ",
         (log_msg == NULL)? US"" : log_msg);
       }
@@ -3118,8 +3156,7 @@ while (done <= 0)
 
 
     case VRFY_CMD:
-    rc = acl_check(ACL_WHERE_VRFY, smtp_data, acl_smtp_vrfy, &user_msg,
-      &log_msg);
+    rc = acl_check(ACL_WHERE_VRFY, NULL, acl_smtp_vrfy, &user_msg, &log_msg);
     if (rc != OK)
       done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg);
     else
@@ -3128,7 +3165,7 @@ while (done <= 0)
       uschar *s = NULL;
 
       /* rfc821_domains = TRUE; << no longer needed */
-      address = parse_extract_address(smtp_data, &errmess, &start, &end,
+      address = parse_extract_address(smtp_command_argument, &errmess, &start, &end,
         &recipient_domain, FALSE);
       /* rfc821_domains = FALSE; << no longer needed */
 
@@ -3155,7 +3192,7 @@ while (done <= 0)
             string_sprintf("550 <%s> %s", address, addr->message) :
             string_sprintf("550 <%s> is not deliverable", address);
           log_write(0, LOG_MAIN, "VRFY failed for %s %s",
-            smtp_data, host_and_ident(TRUE));
+            smtp_command_argument, host_and_ident(TRUE));
           break;
           }
         }
@@ -3166,17 +3203,16 @@ while (done <= 0)
 
 
     case EXPN_CMD:
-    rc = acl_check(ACL_WHERE_EXPN, smtp_data, acl_smtp_expn, &user_msg,
-      &log_msg);
+    rc = acl_check(ACL_WHERE_EXPN, NULL, acl_smtp_expn, &user_msg, &log_msg);
     if (rc != OK)
       done = smtp_handle_acl_fail(ACL_WHERE_EXPN, rc, user_msg, log_msg);
     else
       {
       BOOL save_log_testing_mode = log_testing_mode;
       address_test_mode = log_testing_mode = TRUE;
-      (void) verify_address(deliver_make_addr(smtp_data, FALSE), smtp_out,
-        vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1, NULL, NULL,
-        NULL);
+      (void) verify_address(deliver_make_addr(smtp_command_argument, FALSE),
+        smtp_out, vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1,
+        NULL, NULL, NULL);
       address_test_mode = FALSE;
       log_testing_mode = save_log_testing_mode;    /* true for -bh */
       }
@@ -3303,7 +3339,7 @@ while (done <= 0)
 
     if (acl_smtp_quit != NULL)
       {
-      rc = acl_check(ACL_WHERE_QUIT, US"", acl_smtp_quit,&user_msg,&log_msg);
+      rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit,&user_msg,&log_msg);
       if (rc == ERROR)
         log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s",
           log_msg);
@@ -3392,11 +3428,10 @@ while (done <= 0)
       break;
       }
 
-    log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_data,
+    log_write(L_etrn, LOG_MAIN, "ETRN %s received from %s", smtp_command_argument,
       host_and_ident(FALSE));
 
-    rc = acl_check(ACL_WHERE_ETRN, smtp_data, acl_smtp_etrn, &user_msg,
-      &log_msg);
+    rc = acl_check(ACL_WHERE_ETRN, NULL, acl_smtp_etrn, &user_msg, &log_msg);
     if (rc != OK)
       {
       done = smtp_handle_acl_fail(ACL_WHERE_ETRN, rc, user_msg, log_msg);
@@ -3405,7 +3440,7 @@ while (done <= 0)
 
     /* Compute the serialization key for this command. */
 
-    etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_data);
+    etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_command_argument);
 
     /* If a command has been specified for running as a result of ETRN, we
     permit any argument to ETRN. If not, only the # standard form is permitted,
@@ -3417,7 +3452,7 @@ while (done <= 0)
       uschar *error;
       BOOL rc;
       etrn_command = smtp_etrn_command;
-      deliver_domain = smtp_data;
+      deliver_domain = smtp_command_argument;
       rc = transport_set_up_command(&argv, smtp_etrn_command, TRUE, 0, NULL,
         US"ETRN processing", &error);
       deliver_domain = NULL;
@@ -3434,7 +3469,7 @@ while (done <= 0)
 
     else
       {
-      if (*smtp_data++ != '#')
+      if (*smtp_command_argument++ != '#')
         {
         done = synprot_error(L_smtp_syntax_error, 501, NULL,
           US"argument must begin with #");
@@ -3442,7 +3477,7 @@ while (done <= 0)
         }
       etrn_command = US"exim -R";
       argv = child_exec_exim(CEE_RETURN_ARGV, TRUE, NULL, TRUE, 2, US"-R",
-        smtp_data);
+        smtp_command_argument);
       }
 
     /* If we are host-testing, don't actually do anything. */
@@ -3464,7 +3499,7 @@ while (done <= 0)
 
     if (smtp_etrn_serialize && !enq_start(etrn_serialize_key))
       {
-      smtp_printf("458 Already processing %s\r\n", smtp_data);
+      smtp_printf("458 Already processing %s\r\n", smtp_command_argument);
       break;
       }
 
@@ -3479,9 +3514,9 @@ while (done <= 0)
 
     if ((pid = fork()) == 0)
       {
-      smtp_input = FALSE;    /* This process is not associated with the */
-      fclose(smtp_in);       /* SMTP call any more. */
-      fclose(smtp_out);
+      smtp_input = FALSE;       /* This process is not associated with the */
+      (void)fclose(smtp_in);    /* SMTP call any more. */
+      (void)fclose(smtp_out);
 
       signal(SIGCHLD, SIG_DFL);      /* Want to catch child */
 
@@ -3558,8 +3593,7 @@ while (done <= 0)
     if (c > 150) c = 150;
     smtp_inptr[c] = 0;
     incomplete_transaction_log(US"sync failure");
-    log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol violation: "
-      "synchronization error "
+    log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol synchronization error "
       "(next input sent too soon: pipelining was%s advertised): "
       "rejected \"%s\" %s next input=\"%s\"",
       pipelining_advertised? "" : " not",
@@ -3574,7 +3608,7 @@ while (done <= 0)
     incomplete_transaction_log(US"too many non-mail commands");
     log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many "
       "nonmail commands (last was \"%.*s\")",  host_and_ident(FALSE),
-      smtp_data - cmd_buffer, cmd_buffer);
+      smtp_command_argument - cmd_buffer, cmd_buffer);
     smtp_printf("554 Too many nonmail commands\r\n");
     done = 1;   /* Pretend eof - drops connection */
     break;