JSON: avoid recent library version usage
[exim.git] / src / src / transports / smtp.c
index 7eb6abaeb45b1c9d5f177831bcff5939d0b831ad..a4f44bcada668231eccbd5f1629b00fdf953eb84 100644 (file)
@@ -497,14 +497,13 @@ set_errno(address_item *addrlist, int errno_value, uschar *msg, int rc,
 #endif
   )
 {
-address_item *addr;
 int orvalue = 0;
 if (errno_value == ERRNO_CONNECTTIMEOUT)
   {
   errno_value = ETIMEDOUT;
   orvalue = RTEF_CTOUT;
   }
-for (addr = addrlist; addr; addr = addr->next)
+for (address_item * addr = addrlist; addr; addr = addr->next)
   if (addr->transport_return >= PENDING)
     {
     addr->basic_errno = errno_value;
@@ -668,22 +667,22 @@ Returns:   nothing
 static void
 write_logs(const host_item *host, const uschar *suffix, int basic_errno)
 {
-uschar *message = LOGGING(outgoing_port)
-  ? string_sprintf("H=%s [%s]:%d", host->name, host->address,
+gstring * message = LOGGING(outgoing_port)
+  ? string_fmt_append(NULL, "H=%s [%s]:%d", host->name, host->address,
                    host->port == PORT_NONE ? 25 : host->port)
-  : string_sprintf("H=%s [%s]", host->name, host->address);
+  : string_fmt_append(NULL, "H=%s [%s]", host->name, host->address);
 
 if (suffix)
   {
-  message = string_sprintf("%s: %s", message, suffix);
+  message = string_fmt_append(message, ": %s", suffix);
   if (basic_errno > 0)
-    message = string_sprintf("%s: %s", message, strerror(basic_errno));
+    message = string_fmt_append(message, ": %s", strerror(basic_errno));
   }
 else
-  message = string_sprintf("%s %s", message, exim_errstr(basic_errno));
+  message = string_fmt_append(message, " %s", exim_errstr(basic_errno));
 
-log_write(0, LOG_MAIN, "%s", message);
-deliver_msglog("%s %s\n", tod_stamp(tod_log), message);
+log_write(0, LOG_MAIN, "%s", string_from_gstring(message));
+deliver_msglog("%s %s\n", tod_stamp(tod_log), message->s);
 }
 
 static void
@@ -1197,8 +1196,13 @@ while (count-- > 0)
        If not, log this last one in the == line. */
 
        if (sx->conn_args.host->next)
-         log_write(0, LOG_MAIN, "H=%s [%s]: %s",
-           sx->conn_args.host->name, sx->conn_args.host->address, addr->message);
+         if (LOGGING(outgoing_port))
+           log_write(0, LOG_MAIN, "H=%s [%s]:%d %s", sx->conn_args.host->name,
+             sx->conn_args.host->address,
+             sx->port == PORT_NONE ? 25 : sx->port, addr->message);
+         else
+           log_write(0, LOG_MAIN, "H=%s [%s]: %s", sx->conn_args.host->name,
+             sx->conn_args.host->address, addr->message);
 
 #ifndef DISABLE_EVENT
        else
@@ -1443,7 +1447,7 @@ if (  sx->esmtp
     If one is found, attempt to authenticate by calling its client function.
     */
 
-    for (au = auths; !f.smtp_authenticated && au; au = au->next)
+    for (auth_instance * au = auths; !f.smtp_authenticated && au; au = au->next)
       {
       uschar *p = names;
 
@@ -1596,8 +1600,7 @@ switch (rc)
       DEBUG(D_transport)
        {
        dns_scan dnss;
-       dns_record * rr;
-       for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+       for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
             rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
          if (rr->type == T_TLSA && rr->size > 3)
            {
@@ -2461,7 +2464,6 @@ if (  smtp_peer_options & OPTION_TLS
   else
   TLS_NEGOTIATE:
     {
-    address_item * addr;
     uschar * errstr;
     sx->cctx.tls_ctx = tls_client_start(sx->cctx.sock, sx->conn_args.host,
                            sx->addrlist, sx->conn_args.tblock,
@@ -2499,7 +2501,7 @@ if (  smtp_peer_options & OPTION_TLS
     /* TLS session is set up */
 
     smtp_peer_options_wrap = smtp_peer_options;
-    for (addr = sx->addrlist; addr; addr = addr->next)
+    for (address_item * addr = sx->addrlist; addr; addr = addr->next)
       if (addr->transport_return == PENDING_DEFER)
         {
         addr->cipher = tls_out.cipher;
@@ -2929,8 +2931,8 @@ if (sx->send_quit)
   {
   shutdown(sx->cctx.sock, SHUT_WR);
   if (fcntl(sx->cctx.sock, F_SETFL, O_NONBLOCK) == 0)
-    for (rc = 16; read(sx->cctx.sock, sx->inbuffer, sizeof(sx->inbuffer)) > 0 && rc > 0;)
-      rc--;                            /* drain socket */
+    for (int i = 16; read(sx->cctx.sock, sx->inbuffer, sizeof(sx->inbuffer)) > 0 && i > 0;)
+      i--;                             /* drain socket */
   sx->send_quit = FALSE;
   }
 (void)close(sx->cctx.sock);
@@ -2983,7 +2985,7 @@ request that */
 
 sx->prdr_active = FALSE;
 if (sx->peer_offered & OPTION_PRDR)
-  for (addr = addrlist; addr; addr = addr->next)
+  for (address_item * addr = addrlist; addr; addr = addr->next)
     if (addr->transport_return == PENDING_DEFER)
       {
       for (addr = addr->next; addr; addr = addr->next)
@@ -3068,12 +3070,11 @@ if (sx->peer_offered & OPTION_DSN && !(addr->dsn_flags & rf_dsnlasthop))
   {
   if (addr->dsn_flags & rf_dsnflags)
     {
-    int i;
     BOOL first = TRUE;
 
     Ustrcpy(p, " NOTIFY=");
     while (*p) p++;
-    for (i = 0; i < nelem(rf_list); i++) if (addr->dsn_flags & rf_list[i])
+    for (int i = 0; i < nelem(rf_list); i++) if (addr->dsn_flags & rf_list[i])
       {
       if (!first) *p++ = ',';
       first = FALSE;
@@ -3285,7 +3286,7 @@ smtp_proxy_tls(void * ct_ctx, uschar * buf, size_t bsize, int * pfd,
 {
 fd_set rfds, efds;
 int max_fd = MAX(pfd[0], tls_out.active.sock) + 1;
-int rc, i, fd_bits, nbytes;
+int rc, i;
 
 close(pfd[1]);
 if ((rc = fork()))
@@ -3300,7 +3301,7 @@ FD_ZERO(&rfds);
 FD_SET(tls_out.active.sock, &rfds);
 FD_SET(pfd[0], &rfds);
 
-for (fd_bits = 3; fd_bits; )
+for (int fd_bits = 3; fd_bits; )
   {
   time_t time_left = timeout;
   time_t time_start = time(NULL);
@@ -3343,7 +3344,7 @@ for (fd_bits = 3; fd_bits; )
       }
     else
       {
-      for (nbytes = 0; rc - nbytes > 0; nbytes += i)
+      for (int nbytes = 0; rc - nbytes > 0; nbytes += i)
        if ((i = write(pfd[0], buf + nbytes, rc - nbytes)) < 0) goto done;
       }
   else if (fd_bits & 1)
@@ -3359,7 +3360,7 @@ for (fd_bits = 3; fd_bits; )
       }
     else
       {
-      for (nbytes = 0; rc - nbytes > 0; nbytes += i)
+      for (int nbytes = 0; rc - nbytes > 0; nbytes += i)
        if ((i = tls_write(ct_ctx, buf + nbytes, rc - nbytes, FALSE)) < 0)
          goto done;
       }
@@ -3424,7 +3425,6 @@ smtp_deliver(address_item *addrlist, host_item *host, int host_af, int defport,
   uschar *interface, transport_instance *tblock,
   BOOL *message_defer, BOOL suppress_tls)
 {
-address_item *addr;
 smtp_transport_options_block * ob = SOB tblock->options_block;
 int yield = OK;
 int save_errno;
@@ -3511,14 +3511,12 @@ always has a sequence number greater than one. */
 
 if (continue_hostname && continue_sequence == 1)
   {
-  address_item * addr;
-
   sx.peer_offered = smtp_peer_options;
   sx.pending_MAIL = FALSE;
   sx.ok = TRUE;
   sx.next_addr = NULL;
 
-  for (addr = addrlist; addr; addr = addr->next)
+  for (address_item * addr = addrlist; addr; addr = addr->next)
     addr->transport_return = PENDING_OK;
   }
 else
@@ -3810,7 +3808,7 @@ else
     /* Process all transported addresses - for LMTP or PRDR, read a status for
     each one. */
 
-    for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+    for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
       {
       if (addr->transport_return != PENDING_OK) continue;
 
@@ -3925,7 +3923,7 @@ else
             errno = ERRNO_DATA4XX;
             addrlist->more_errno |= ((sx.buffer[1] - '0')*10 + sx.buffer[2] - '0') << 8;
             }
-         for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+         for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
             if (sx.buffer[0] == '5' || addr->transport_return == OK)
               addr->transport_return = PENDING_OK; /* allow set_errno action */
          goto RESPONSE_FAILED;
@@ -3935,11 +3933,11 @@ else
        and update the journal, or setup retry. */
 
        overall_message = string_printing(sx.buffer);
-        for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+        for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
          if (addr->transport_return == OK)
            addr->message = string_sprintf("%s\\n%s", addr->message, overall_message);
 
-        for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+        for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
          if (addr->transport_return == OK)
            {
            if (testflag(addr, af_homonym))
@@ -4323,6 +4321,9 @@ This change is being made on 31-Jul-98. After over a year of trouble-free
 operation, the old commented-out code was removed on 17-Sep-99. */
 
 SEND_QUIT:
+#ifdef TCP_CORK
+(void) setsockopt(sx.cctx.sock, IPPROTO_TCP, TCP_CORK, US &on, sizeof(on));
+#endif
 if (sx.send_quit) (void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");
 
 END_OFF:
@@ -4348,8 +4349,8 @@ if (sx.send_quit)
   shutdown(sx.cctx.sock, SHUT_WR);
   millisleep(f.running_in_test_harness ? 200 : 20);
   if (fcntl(sx.cctx.sock, F_SETFL, O_NONBLOCK) == 0)
-    for (rc = 16; read(sx.cctx.sock, sx.inbuffer, sizeof(sx.inbuffer)) > 0 && rc > 0;)
-      rc--;                            /* drain socket */
+    for (int i = 16; read(sx.cctx.sock, sx.inbuffer, sizeof(sx.inbuffer)) > 0 && i > 0;)
+      i--;                             /* drain socket */
   }
 (void)close(sx.cctx.sock);
 
@@ -4438,8 +4439,7 @@ static address_item *
 prepare_addresses(address_item *addrlist, host_item *host)
 {
 address_item *first_addr = NULL;
-address_item *addr;
-for (addr = addrlist; addr; addr = addr->next)
+for (address_item * addr = addrlist; addr; addr = addr->next)
   if (addr->transport_return == DEFER)
     {
     if (!first_addr) first_addr = addr;
@@ -4479,7 +4479,6 @@ smtp_transport_entry(
   transport_instance *tblock,      /* data for this instantiation */
   address_item *addrlist)          /* addresses we are working on */
 {
-int cutoff_retry;
 int defport;
 int hosts_defer = 0;
 int hosts_fail  = 0;
@@ -4488,24 +4487,23 @@ int hosts_retry = 0;
 int hosts_serial = 0;
 int hosts_total = 0;
 int total_hosts_tried = 0;
-address_item *addr;
 BOOL expired = TRUE;
 uschar *expanded_hosts = NULL;
 uschar *pistring;
 uschar *tid = string_sprintf("%s transport", tblock->name);
 smtp_transport_options_block *ob = SOB tblock->options_block;
 host_item *hostlist = addrlist->host_list;
-host_item *host;
+host_item *host = NULL;
 
 DEBUG(D_transport)
   {
   debug_printf("%s transport entered\n", tblock->name);
-  for (addr = addrlist; addr; addr = addr->next)
+  for (address_item * addr = addrlist; addr; addr = addr->next)
     debug_printf("  %s\n", addr->address);
   if (hostlist)
     {
     debug_printf("hostlist:\n");
-    for (host = hostlist; host; host = host->next)
+    for (host_item * host = hostlist; host; host = host->next)
       debug_printf("  '%s' IP %s port %d\n", host->name, host->address, host->port);
     }
   if (continue_hostname)
@@ -4687,7 +4685,7 @@ the current message. To cope with this, we have to go round the loop a second
 time. After that, set the status and error data for any addresses that haven't
 had it set already. */
 
-for (cutoff_retry = 0;
+for (int cutoff_retry = 0;
      expired && cutoff_retry < (ob->delay_after_cutoff ? 1 : 2);
      cutoff_retry++)
   {
@@ -4737,7 +4735,6 @@ retry_non_continued:
     if (!host->address)
       {
       int new_port, flags;
-      host_item *hh;
 
       if (host->status >= hstatus_unusable)
         {
@@ -4774,7 +4771,7 @@ retry_non_continued:
       /* Update the host (and any additional blocks, resulting from
       multihoming) with a host-specific port, if any. */
 
-      for (hh = host; hh != nexthost; hh = hh->next) hh->port = new_port;
+      for (host_item * hh = host; hh != nexthost; hh = hh->next) hh->port = new_port;
 
       /* Failure to find the host at this time (usually DNS temporary failure)
       is really a kind of routing failure rather than a transport failure.
@@ -4793,7 +4790,7 @@ retry_non_continued:
           "HOST_FIND_AGAIN" : "HOST_FIND_FAILED", host->name);
         host->status = hstatus_unusable;
 
-        for (addr = addrlist; addr; addr = addr->next)
+        for (address_item * addr = addrlist; addr; addr = addr->next)
           {
           if (addr->transport_return != DEFER) continue;
           addr->basic_errno = ERRNO_UNKNOWNHOST;
@@ -4812,7 +4809,7 @@ retry_non_continued:
 
       if (rc == HOST_FOUND_LOCAL && !ob->allow_localhost)
         {
-        for (addr = addrlist; addr; addr = addr->next)
+        for (address_item * addr = addrlist; addr; addr = addr->next)
           {
           addr->basic_errno = 0;
           addr->message = string_sprintf("%s transport found host %s to be "
@@ -4857,7 +4854,7 @@ retry_non_continued:
           &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK))
       {
       expired = FALSE;
-      for (addr = addrlist; addr; addr = addr->next)
+      for (address_item * addr = addrlist; addr; addr = addr->next)
         if (addr->transport_return == DEFER)
          addr->message = US"domain matches queue_smtp_domains, or -odqs set";
       continue;      /* With next host */
@@ -4922,10 +4919,10 @@ retry_non_continued:
         incl_ip, &retry_host_key, &retry_message_key);
 
       DEBUG(D_transport) debug_printf("%s [%s]%s retry-status = %s\n", host->name,
-        (host->address == NULL)? US"" : host->address, pistring,
-        (host->status == hstatus_usable)? "usable" :
-        (host->status == hstatus_unusable)? "unusable" :
-        (host->status == hstatus_unusable_expired)? "unusable (expired)" : "?");
+        host->address ? host->address : US"", pistring,
+        host->status == hstatus_usable ? "usable"
+        : host->status == hstatus_unusable ? "unusable"
+        : host->status == hstatus_unusable_expired ? "unusable (expired)" : "?");
 
       /* Skip this address if not usable at this time, noting if it wasn't
       actually expired, both locally and in the address. */
@@ -5008,8 +5005,8 @@ retry_non_continued:
       message_id, host->name, host->address, addrlist->address,
       addrlist->next ? ", ..." : "");
 
-    set_process_info("delivering %s to %s [%s] (%s%s)",
-      message_id, host->name, host->address, addrlist->address,
+    set_process_info("delivering %s to %s [%s]%s (%s%s)",
+      message_id, host->name, host->address, pistring, addrlist->address,
       addrlist->next ? ", ..." : "");
 
     /* This is not for real; don't do the delivery. If there are
@@ -5017,9 +5014,8 @@ retry_non_continued:
 
     if (f.dont_deliver)
       {
-      host_item *host2;
       set_errno_nohost(addrlist, 0, NULL, OK, FALSE);
-      for (addr = addrlist; addr; addr = addr->next)
+      for (address_item * addr = addrlist; addr; addr = addr->next)
         {
         addr->host_used = host;
         addr->special_action = '*';
@@ -5029,7 +5025,7 @@ retry_non_continued:
         {
         debug_printf("*** delivery by %s transport bypassed by -N option\n"
                      "*** host and remaining hosts:\n", tblock->name);
-        for (host2 = host; host2; host2 = host2->next)
+        for (host_item * host2 = host; host2; host2 = host2->next)
           debug_printf("    %s [%s]\n", host2->name,
             host2->address ? host2->address : US"unset");
         }
@@ -5067,10 +5063,9 @@ retry_non_continued:
 
       if (!host_is_expired && ++unexpired_hosts_tried >= ob->hosts_max_try)
         {
-        host_item *h;
         DEBUG(D_transport)
           debug_printf("hosts_max_try limit reached with this host\n");
-        for (h = host; h; h = h->next) if (h->mx != host->mx)
+        for (host_item * h = host; h; h = h->next) if (h->mx != host->mx)
          {
          nexthost = h;
          unexpired_hosts_tried--;
@@ -5149,8 +5144,8 @@ retry_non_continued:
        : rc == ERROR ? US"ERROR"
        : US"?";
 
-    set_process_info("delivering %s: just tried %s [%s] for %s%s: result %s",
-      message_id, host->name, host->address, addrlist->address,
+    set_process_info("delivering %s: just tried %s [%s]%s for %s%s: result %s",
+      message_id, host->name, host->address, pistring, addrlist->address,
       addrlist->next ? " (& others)" : "", rs);
 
     /* Release serialization if set up */
@@ -5239,7 +5234,7 @@ retry_non_continued:
     case, see if any of them are deferred. */
 
     if (rc == OK)
-      for (addr = addrlist; addr; addr = addr->next)
+      for (address_item * addr = addrlist; addr; addr = addr->next)
         if (addr->transport_return == DEFER)
           {
           some_deferred = TRUE;
@@ -5293,6 +5288,17 @@ retry_non_continued:
           "hosts_max_try (message older than host's retry time)\n");
         }
       }
+
+    DEBUG(D_transport)
+      {
+      if (unexpired_hosts_tried >= ob->hosts_max_try)
+       debug_printf("reached transport hosts_max_try limit %d\n",
+         ob->hosts_max_try);
+      if (total_hosts_tried >= ob->hosts_max_try_hardlimit)
+       debug_printf("reached transport hosts_max_try_hardlimit limit %d\n",
+         ob->hosts_max_try_hardlimit);
+      }
+
     if (f.running_in_test_harness) millisleep(500); /* let server debug out */
     }   /* End of loop for trying multiple hosts. */
 
@@ -5347,7 +5353,7 @@ specific failures. Force the delivery status for all addresses to FAIL. */
 
 if (mua_wrapper)
   {
-  for (addr = addrlist; addr; addr = addr->next)
+  for (address_item * addr = addrlist; addr; addr = addr->next)
     addr->transport_return = FAIL;
   goto END_TRANSPORT;
   }
@@ -5364,7 +5370,7 @@ If queue_smtp is set, or this transport was called to send a subsequent message
 down an existing TCP/IP connection, and something caused the host not to be
 found, we end up here, but can detect these cases and handle them specially. */
 
-for (addr = addrlist; addr; addr = addr->next)
+for (address_item * addr = addrlist; addr; addr = addr->next)
   {
   /* If host is not NULL, it means that we stopped processing the host list
   because of hosts_max_try or hosts_max_try_hardlimit. In the former case, this