GNU/Hurd: retry EINTR returns from pipe I/O
[exim.git] / src / src / deliver.c
index 5fc748141b681a7d57aebec6a865cb4d0d294cb7..8c05934483a10d183cae2aedfc12bf7bded28e9a 100644 (file)
@@ -1221,7 +1221,7 @@ else
     {
     if (testflag(addr, af_pipelining))
       g = string_catn(g, US" L", 2);
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
     if (testflag(addr, af_early_pipe))
       g = string_catn(g, US"*", 1);
 #endif
@@ -1610,6 +1610,7 @@ if (result == OK)
   tls_out.peercert = addr->peercert;
   addr->peercert = NULL;
 
+  tls_out.ver = addr->tlsver;
   tls_out.cipher = addr->cipher;
   tls_out.peerdn = addr->peerdn;
   tls_out.ocsp = addr->ocsp;
@@ -1623,6 +1624,7 @@ if (result == OK)
 #ifndef DISABLE_TLS
   tls_free_cert(&tls_out.ourcert);
   tls_free_cert(&tls_out.peercert);
+  tls_out.ver = NULL;
   tls_out.cipher = NULL;
   tls_out.peerdn = NULL;
   tls_out.ocsp = OCSP_NOT_REQ;
@@ -2400,14 +2402,14 @@ if ((pid = fork()) == 0)
     uschar *s;
     int ret;
 
-    if(  (ret = write(pfd[pipe_write], &addr2->transport_return, sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &transport_count, sizeof(transport_count))) != sizeof(transport_count)
-      || (ret = write(pfd[pipe_write], &addr2->flags, sizeof(addr2->flags))) != sizeof(addr2->flags)
-      || (ret = write(pfd[pipe_write], &addr2->basic_errno,    sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->more_errno,     sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->delivery_usec,  sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->special_action, sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->transport,
+    if(  (ret = os_pipe_write(pfd[pipe_write], &addr2->transport_return, sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &transport_count, sizeof(transport_count))) != sizeof(transport_count)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->flags, sizeof(addr2->flags))) != sizeof(addr2->flags)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->basic_errno,    sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->more_errno,     sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->delivery_usec,  sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->special_action, sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->transport,
         sizeof(transport_instance *))) != sizeof(transport_instance *)
 
     /* For a file delivery, pass back the local part, in case the original
@@ -2415,8 +2417,8 @@ if ((pid = fork()) == 0)
     logging. */
 
       || (testflag(addr2, af_file)
-          && (  (ret = write(pfd[pipe_write], &local_part_length, sizeof(int))) != sizeof(int)
-             || (ret = write(pfd[pipe_write], addr2->local_part, local_part_length)) != local_part_length
+          && (  (ret = os_pipe_write(pfd[pipe_write], &local_part_length, sizeof(int))) != sizeof(int)
+             || (ret = os_pipe_write(pfd[pipe_write], addr2->local_part, local_part_length)) != local_part_length
             )
         )
       )
@@ -2428,8 +2430,8 @@ if ((pid = fork()) == 0)
     for (i = 0, s = addr2->message; i < 2; i++, s = addr2->user_message)
       {
       int message_length = s ? Ustrlen(s) + 1 : 0;
-      if(  (ret = write(pfd[pipe_write], &message_length, sizeof(int))) != sizeof(int)
-        || message_length > 0  && (ret = write(pfd[pipe_write], s, message_length)) != message_length
+      if(  (ret = os_pipe_write(pfd[pipe_write], &message_length, sizeof(int))) != sizeof(int)
+        || message_length > 0  && (ret = os_pipe_write(pfd[pipe_write], s, message_length)) != message_length
        )
         log_write(0, LOG_MAIN|LOG_PANIC, "Failed writing transport results to pipe: %s",
          ret == -1 ? strerror(errno) : "short write");
@@ -2462,26 +2464,26 @@ will remain. Afterwards, close the reading end. */
 
 for (addr2 = addr; addr2; addr2 = addr2->next)
   {
-  if ((len = read(pfd[pipe_read], &status, sizeof(int))) > 0)
+  if ((len = os_pipe_read(pfd[pipe_read], &status, sizeof(int))) > 0)
     {
     int i;
     uschar **sptr;
 
     addr2->transport_return = status;
-    len = read(pfd[pipe_read], &transport_count,
+    len = os_pipe_read(pfd[pipe_read], &transport_count,
       sizeof(transport_count));
-    len = read(pfd[pipe_read], &addr2->flags, sizeof(addr2->flags));
-    len = read(pfd[pipe_read], &addr2->basic_errno,    sizeof(int));
-    len = read(pfd[pipe_read], &addr2->more_errno,     sizeof(int));
-    len = read(pfd[pipe_read], &addr2->delivery_usec,  sizeof(int));
-    len = read(pfd[pipe_read], &addr2->special_action, sizeof(int));
-    len = read(pfd[pipe_read], &addr2->transport,
+    len = os_pipe_read(pfd[pipe_read], &addr2->flags, sizeof(addr2->flags));
+    len = os_pipe_read(pfd[pipe_read], &addr2->basic_errno,    sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->more_errno,     sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->delivery_usec,  sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->special_action, sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->transport,
       sizeof(transport_instance *));
 
     if (testflag(addr2, af_file))
       {
       int llen;
-      if (  read(pfd[pipe_read], &llen, sizeof(int)) != sizeof(int)
+      if (  os_pipe_read(pfd[pipe_read], &llen, sizeof(int)) != sizeof(int)
         || llen > 64*4 /* limit from rfc 5821, times I18N factor */
          )
        {
@@ -2491,7 +2493,7 @@ for (addr2 = addr; addr2; addr2 = addr2->next)
        }
       /* sanity-checked llen so disable the Coverity error */
       /* coverity[tainted_data] */
-      if (read(pfd[pipe_read], big_buffer, llen) != llen)
+      if (os_pipe_read(pfd[pipe_read], big_buffer, llen) != llen)
        {
        log_write(0, LOG_MAIN|LOG_PANIC, "bad local_part read"
          " from delivery subprocess");
@@ -2504,10 +2506,10 @@ for (addr2 = addr; addr2; addr2 = addr2->next)
     for (i = 0, sptr = &addr2->message; i < 2; i++, sptr = &addr2->user_message)
       {
       int message_length;
-      len = read(pfd[pipe_read], &message_length, sizeof(int));
+      len = os_pipe_read(pfd[pipe_read], &message_length, sizeof(int));
       if (message_length > 0)
         {
-        len = read(pfd[pipe_read], big_buffer, message_length);
+        len = os_pipe_read(pfd[pipe_read], big_buffer, message_length);
        big_buffer[big_buffer_size-1] = '\0';           /* guard byte */
         if (len > 0) *sptr = string_copy(big_buffer);
         }
@@ -3480,11 +3482,13 @@ while (!done)
       switch (*subid)
        {
        case '1':
-         addr->cipher = NULL;
-         addr->peerdn = NULL;
+         addr->tlsver = addr->cipher = addr->peerdn = NULL;
 
          if (*ptr)
+           {
            addr->cipher = string_copy(ptr);
+           addr->tlsver = string_copyn(ptr, Ustrchr(ptr, ':') - ptr);
+           }
          while (*ptr++);
          if (*ptr)
            addr->peerdn = string_copy(ptr);
@@ -3533,7 +3537,7 @@ while (!done)
     case 'L':
       switch (*subid)
        {
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
        case 2: setflag(addr, af_early_pipe);   /*FALLTHROUGH*/
 #endif
        case 1: setflag(addr, af_pipelining); break;
@@ -4143,7 +4147,7 @@ if (PIPE_HEADER_SIZE != snprintf(CS pipe_header, PIPE_HEADER_SIZE+1, "%c%c%05ld"
 DEBUG(D_deliver) debug_printf("header write id:%c,subid:%c,size:%ld,final:%s\n",
                                  id, subid, (long)size, pipe_header);
 
-if ((ret = writev(fd, iov, 2)) != total_len)
+if ((ret = os_pipe_writev(fd, iov, 2)) != total_len)
   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
     "Failed writing transport result to pipe (%ld of %ld bytes): %s",
     (long)ret, (long)total_len, ret == -1 ? strerror(errno) : "short write");
@@ -4840,7 +4844,7 @@ all pipes, so I do not see a reason to use non-blocking IO here
 #endif
 
       if (testflag(addr, af_pipelining))
-#ifdef SUPPORT_PIPE_CONNECT
+#ifndef DISABLE_PIPE_CONNECT
        if (testflag(addr, af_early_pipe))
          rmt_dlv_checked_write(fd, 'L', '2', NULL, 0);
        else
@@ -5024,9 +5028,10 @@ all pipes, so I do not see a reason to use non-blocking IO here
 
   /* Otherwise, if we are running in the test harness, wait a bit, to let the
   newly created process get going before we create another process. This should
-  ensure repeatability in the tests. We only need to wait a tad. */
+  ensure repeatability in the tests. Wait long enough for most cases to complete
+  the transport. */
 
-  else testharness_pause_ms(500);
+  else testharness_pause_ms(600);
 
   continue;
 
@@ -5473,6 +5478,26 @@ fprintf(f, "Action: %s\n"
 }
 
 
+
+/* When running in the test harness, there's an option that allows us to
+fudge this time so as to get repeatability of the tests. Take the first
+time off the list. In queue runs, the list pointer gets updated in the
+calling process. */
+
+int
+test_harness_fudged_queue_time(int actual_time)
+{
+int qt;
+if (  f.running_in_test_harness && *fudged_queue_times
+   && (qt = readconf_readtime(fudged_queue_times, '/', FALSE)) >= 0)
+  {
+  DEBUG(D_deliver) debug_printf("fudged queue_times = %s\n",
+    fudged_queue_times);
+  return qt;
+  }
+return actual_time;
+}
+
 /*************************************************
 *              Deliver one message               *
 *************************************************/
@@ -6163,7 +6188,8 @@ if (process_recipients != RECIP_IGNORE)
         new->onetime_parent = recipients_list[r->pno].address;
 
       /* If DSN support is enabled, set the dsn flags and the original receipt
-         to be passed on to other DSN enabled MTAs */
+      to be passed on to other DSN enabled MTAs */
+
       new->dsn_flags = r->dsn_flags & rf_dsnflags;
       new->dsn_orcpt = r->orcpt;
       DEBUG(D_deliver) debug_printf("DSN: set orcpt: %s  flags: 0x%x\n",
@@ -7283,10 +7309,9 @@ for (address_item * a = addr_succeed; a; a = a->next)
       );
 
   /* send report if next hop not DSN aware or a router flagged "last DSN hop"
-     and a report was requested */
-  if (  (  a->dsn_aware != dsn_support_yes
-       || a->dsn_flags & rf_dsnlasthop
-        )
+  and a report was requested */
+
+  if (  (a->dsn_aware != dsn_support_yes || a->dsn_flags & rf_dsnlasthop)
      && a->dsn_flags & rf_notify_success
      )
     {
@@ -8130,21 +8155,7 @@ else if (addr_defer != (address_item *)(+1))
     int show_time;
     int queue_time = time(NULL) - received_time.tv_sec;
 
-    /* When running in the test harness, there's an option that allows us to
-    fudge this time so as to get repeatability of the tests. Take the first
-    time off the list. In queue runs, the list pointer gets updated in the
-    calling process. */
-
-    if (f.running_in_test_harness && fudged_queue_times[0] != 0)
-      {
-      int qt = readconf_readtime(fudged_queue_times, '/', FALSE);
-      if (qt >= 0)
-        {
-        DEBUG(D_deliver) debug_printf("fudged queue_times = %s\n",
-          fudged_queue_times);
-        queue_time = qt;
-        }
-      }
+    queue_time = test_harness_fudged_queue_time(queue_time);
 
     /* See how many warnings we should have sent by now */