Move native sha1 implementation from auths to toplevel, only used for non-TLS builds
[exim.git] / src / src / transport.c
index c7687369875bc486257385a6d730413e2d8ab58b..86350ba9d8ccee39061081d9ea34d449c95830b5 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2014 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* General functions concerned with transportation, and generic options for all
@@ -66,7 +66,7 @@ optionlist optionlist_transports[] = {
                  (void *)offsetof(transport_instance, driver_name) },
   { "envelope_to_add",   opt_bool|opt_public,
                  (void *)(offsetof(transport_instance, envelope_to_add)) },
-#ifdef EXPERIMENTAL_EVENT
+#ifndef DISABLE_EVENT
   { "event_action",     opt_stringptr | opt_public,
                  (void *)offsetof(transport_instance, event_action) },
 #endif
@@ -84,6 +84,8 @@ optionlist optionlist_transports[] = {
                  (void *)offsetof(transport_instance, home_dir) },
   { "initgroups",       opt_bool|opt_public,
                  (void *)offsetof(transport_instance, initgroups) },
+  { "max_parallel",     opt_stringptr|opt_public,
+                 (void *)offsetof(transport_instance, max_parallel) },
   { "message_size_limit", opt_stringptr|opt_public,
                  (void *)offsetof(transport_instance, message_size_limit) },
   { "rcpt_include_affixes", opt_bool|opt_public,
@@ -628,7 +630,7 @@ that means they were rewritten, or are a record of envelope rewriting, or
 were removed (e.g. Bcc). If remove_headers is not null, skip any headers that
 match any entries therein.  It is a colon-sep list; expand the items
 separately and squash any empty ones.
-Then check addr->p.remove_headers too, provided that addr is not NULL. */
+Then check addr->prop.remove_headers too, provided that addr is not NULL. */
 
 for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
   {
@@ -637,7 +639,7 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
 
   BOOL include_header = TRUE;
 
-  for (i = 0; i < 2; i++)    /* For remove_headers && addr->p.remove_headers */
+  for (i = 0; i < 2; i++)    /* For remove_headers && addr->prop.remove_headers */
     {
     if (list)
       {
@@ -653,7 +655,7 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
            errno = ERRNO_CHHEADER_FAIL;
            return FALSE;
            }
-       len = Ustrlen(s);
+       len = s ? Ustrlen(s) : 0;
        if (strncmpic(h->text, s, len) != 0) continue;
        ss = h->text + len;
        while (*ss == ' ' || *ss == '\t') ss++;
@@ -661,7 +663,7 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
        }
       if (s != NULL) { include_header = FALSE; break; }
       }
-    if (addr != NULL) list = addr->p.remove_headers;
+    if (addr != NULL) list = addr->prop.remove_headers;
     }
 
   /* If this header is to be output, try to rewrite it if there are rewriting
@@ -709,7 +711,7 @@ Headers added to an address by a router are guaranteed to end with a newline.
 if (addr)
   {
   int i;
-  header_line *hprev = addr->p.extra_headers;
+  header_line *hprev = addr->prop.extra_headers;
   header_line *hnext;
   for (i = 0; i < 2; i++)
     {
@@ -914,7 +916,7 @@ if ((options & topt_no_headers) == 0)
   /* Then the message's headers. Don't write any that are flagged as "old";
   that means they were rewritten, or are a record of envelope rewriting, or
   were removed (e.g. Bcc). If remove_headers is not null, skip any headers that
-  match any entries therein. Then check addr->p.remove_headers too, provided that
+  match any entries therein. Then check addr->prop.remove_headers too, provided that
   addr is not NULL. */
   if (!transport_headers_send(addr, fd, add_headers, remove_headers, &write_chunk,
        use_crlf, rewrite_rules, rewrite_existflags))
@@ -931,7 +933,8 @@ if ((options & topt_no_body) == 0)
   {
   nl_check_length = abs(nl_check_length);
   nl_partial_match = 0;
-  lseek(deliver_datafile, SPOOL_DATA_START_OFFSET, SEEK_SET);
+  if (lseek(deliver_datafile, SPOOL_DATA_START_OFFSET, SEEK_SET) < 0)
+    return FALSE;
   while ((len = read(deliver_datafile, deliver_in_buffer,
            DELIVER_IN_BUFFER_SIZE)) > 0)
     {
@@ -1066,7 +1069,7 @@ if (dkim_private_key && dkim_domain && dkim_selector)
       uschar *dkim_strict_result = expand_string(dkim_strict);
       if (dkim_strict_result)
        if ( (strcmpic(dkim_strict,US"1") == 0) ||
-            (strcmpic(dkim_strict,US"true") == 0) ) 
+            (strcmpic(dkim_strict,US"true") == 0) )
          {
          /* Set errno to something halfway meaningful */
          save_errno = EACCES;
@@ -1203,7 +1206,7 @@ transport_write_message(address_item *addr, int fd, int options,
 BOOL use_crlf;
 BOOL last_filter_was_NL = TRUE;
 int rc, len, yield, fd_read, fd_write, save_errno;
-int pfd[2];
+int pfd[2] = {-1, -1};
 pid_t filter_pid, write_pid;
 
 transport_filter_timed_out = FALSE;
@@ -1211,7 +1214,10 @@ transport_filter_timed_out = FALSE;
 /* If there is no filter command set up, call the internal function that does
 the actual work, passing it the incoming fd, and return its result. */
 
-if (transport_filter_argv == NULL)
+if (  !transport_filter_argv
+   || !*transport_filter_argv
+   || !**transport_filter_argv
+   )
   return internal_transport_write_message(addr, fd, options, size_limit,
     add_headers, remove_headers, check_string, escape_string,
     rewrite_rules, rewrite_existflags);
@@ -1643,20 +1649,15 @@ transport_check_waiting(const uschar *transport_name, const uschar *hostname,
   int local_message_max, uschar *new_message_id, BOOL *more, oicf oicf_func, void *oicf_data)
 {
 dbdata_wait *host_record;
-int host_length, path_len;
+int host_length;
 open_db dbblock;
 open_db *dbm_file;
 uschar buffer[256];
 
-msgq_t      *msgq = NULL;
-int         msgq_count = 0;
-int         msgq_actual = 0;
 int         i;
-BOOL        bFound = FALSE;
 uschar      spool_dir [PATH_MAX];
 uschar      spool_file [PATH_MAX];
 struct stat statbuf;
-BOOL        bContinuation = FALSE;
 
 *more = FALSE;
 
@@ -1686,8 +1687,7 @@ if (dbm_file == NULL) return FALSE;
 
 /* See if there is a record for this host; if not, there's nothing to do. */
 
-host_record = dbfn_read(dbm_file, hostname);
-if (host_record == NULL)
+if (!(host_record = dbfn_read(dbm_file, hostname)))
   {
   dbfn_close(dbm_file);
   DEBUG(D_transport) debug_printf("no messages waiting for %s\n", hostname);
@@ -1720,6 +1720,12 @@ host_length = host_record->count * MESSAGE_ID_LENGTH;
 
 while (1)
   {
+  msgq_t      *msgq;
+  int         msgq_count = 0;
+  int         msgq_actual = 0;
+  BOOL        bFound = FALSE;
+  BOOL        bContinuation = FALSE;
+
   /* create an array to read entire message queue into memory for processing  */
 
   msgq = (msgq_t*) malloc(sizeof(msgq_t) * host_record->count);
@@ -1746,13 +1752,11 @@ while (1)
 
   /* now find the next acceptable message_id */
 
-  bFound = FALSE;
-
   for (i = msgq_count - 1; i >= 0; --i) if (msgq[i].bKeep)
     {
     if (split_spool_directory)
        sprintf(CS spool_file, "%s%c/%s-D",
-                     spool_dir, new_message_id[5], msgq[i].message_id);
+                     spool_dir, msgq[i].message_id[5], msgq[i].message_id);
     else
        sprintf(CS spool_file, "%s%s-D", spool_dir, msgq[i].message_id);
 
@@ -1773,8 +1777,7 @@ while (1)
       msgq_actual++;
 
   /* reassemble the host record, based on removed message ids, from in
-   * memory queue.
-   */
+  memory queue  */
 
   if (msgq_actual <= 0)
     {
@@ -1801,8 +1804,6 @@ while (1)
 /* Jeremy: check for a continuation record, this code I do not know how to
 test but the code should work */
 
-  bContinuation = FALSE;
-
   while (host_length <= 0)
     {
     int i;
@@ -1833,8 +1834,11 @@ test but the code should work */
     bContinuation = TRUE;
     }
 
-  if (bFound)
+  if (bFound)          /* Usual exit from main loop */
+    {
+    free (msgq);
     break;
+    }
 
   /* If host_length <= 0 we have emptied a record and not found a good message,
   and there are no continuation records. Otherwise there is a continuation
@@ -1853,20 +1857,13 @@ test but the code should work */
 
   if (!bContinuation)
     {
-    Ustrcpy (new_message_id, message_id); 
+    Ustrcpy(new_message_id, message_id);
     dbfn_close(dbm_file);
     return FALSE;
     }
-  }            /* we need to process a continuation record */
 
-/* clean up in memory queue */
-if (msgq)
-  {
-  free (msgq);
-  msgq = NULL;
-  msgq_count = 0;
-  msgq_actual = 0;
-  }
+  free(msgq);
+  }            /* we need to process a continuation record */
 
 /* Control gets here when an existing message has been encountered; its
 id is in new_message_id, and host_length is the revised length of the
@@ -1875,19 +1872,8 @@ record if required, close the database, and return TRUE. */
 
 if (host_length > 0)
   {
-  uschar  msg [MESSAGE_ID_LENGTH + 1];
-  int i;
-
   host_record->count = host_length/MESSAGE_ID_LENGTH;
 
-  /* rebuild the host_record->text */
-
-  for (i = 0; i < host_record->count; ++i)
-    {
-    Ustrncpy(msg, host_record->text + (i*MESSAGE_ID_LENGTH), MESSAGE_ID_LENGTH);
-    msg[MESSAGE_ID_LENGTH] = 0;
-    }
-
   dbfn_write(dbm_file, hostname, host_record, (int)sizeof(dbdata_wait) + host_length);
   *more = TRUE;
   }