Copyright updates:
[exim.git] / src / src / transports / autoreply.c
index 4b5ef8e1748844934fb948b1e31bdb2399523911..6110f87bff713e3e9fdd3a4061ca7aecae96dcbd 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -174,18 +175,21 @@ return ss;
 list. Any that are found are removed.
 
 Arguments:
-  listptr     points to the list of addresses
+  list        list of addresses to be checked
   never_mail  an address list, already expanded
 
-Returns:      nothing
+Returns:      edited replacement address list, or NULL, or original
 */
 
-static void
-check_never_mail(uschar **listptr, const uschar *never_mail)
+static uschar *
+check_never_mail(uschar * list, const uschar * never_mail)
 {
-uschar *s = *listptr;
+rmark reset_point = store_mark();
+uschar * newlist = string_copy(list);
+uschar * s = newlist;
+BOOL hit = FALSE;
 
-while (*s != 0)
+while (*s)
   {
   uschar *error, *next;
   uschar *e = parse_find_address_end(s, FALSE);
@@ -202,7 +206,7 @@ while (*s != 0)
   /* If there is some kind of syntax error, just give up on this header
   line. */
 
-  if (next == NULL) break;
+  if (!next) break;
 
   /* See if the address is on the never_mail list */
 
@@ -219,6 +223,7 @@ while (*s != 0)
     {
     DEBUG(D_transport)
       debug_printf("discarding recipient %s (matched never_mail)\n", next);
+    hit = TRUE;
     if (terminator == ',') e++;
     memmove(s, e, Ustrlen(e) + 1);
     }
@@ -229,18 +234,31 @@ while (*s != 0)
     }
   }
 
+/* If no addresses were removed, retrieve the memory used and return
+the original. */
+
+if (!hit)
+  {
+  store_reset(reset_point);
+  return list;
+  }
+
 /* Check to see if we removed the last address, leaving a terminating comma
 that needs to be removed */
 
-s = *listptr + Ustrlen(*listptr);
-while (s > *listptr && (isspace(s[-1]) || s[-1] == ',')) s--;
+s = newlist + Ustrlen(newlist);
+while (s > newlist && (isspace(s[-1]) || s[-1] == ',')) s--;
 *s = 0;
 
-/* Check to see if there any addresses left; if not, set NULL */
+/* Check to see if there any addresses left; if not, return NULL */
 
-s = *listptr;
-while (s != 0 && isspace(*s)) s++;
-if (*s == 0) *listptr = NULL;
+s = newlist;
+while (s && isspace(*s)) s++;
+if (*s)
+  return newlist;
+
+store_reset(reset_point);
+return NULL;
 }
 
 
@@ -371,9 +389,9 @@ if (ob->never_mail)
     return FALSE;
     }
 
-  if (to) check_never_mail(&to, never_mail);
-  if (cc) check_never_mail(&cc, never_mail);
-  if (bcc) check_never_mail(&bcc, never_mail);
+  if (to) to = check_never_mail(to, never_mail);
+  if (cc) cc = check_never_mail(cc, never_mail);
+  if (bcc) bcc = check_never_mail(bcc, never_mail);
 
   if (!to && !cc && !bcc)
     {
@@ -403,14 +421,15 @@ recipient cache. */
 
 if (oncelog && *oncelog && to)
   {
+  uschar *m;
   time_t then = 0;
 
-  if (is_tainted(oncelog))
+  if ((m = is_tainted2(oncelog, 0, "Tainted '%s' (once file for %s transport)"
+      " not permitted", oncelog, tblock->name)))
     {
     addr->transport_return = DEFER;
     addr->basic_errno = EACCES;
-    addr->message = string_sprintf("Tainted '%s' (once file for %s transport)"
-      " not permitted", oncelog, tblock->name);
+    addr->message = m;
     goto END_OFF;
     }
 
@@ -473,10 +492,10 @@ if (oncelog && *oncelog && to)
   else
     {
     EXIM_DATUM key_datum, result_datum;
-    uschar * dirname = string_copy(oncelog);
-    uschar * s;
+    uschar * dirname, * s;
 
-    if ((s = Ustrrchr(dirname, '/'))) *s = '\0';
+    dirname = (s = Ustrrchr(oncelog, '/'))
+      ? string_copyn(oncelog, s - oncelog) : NULL;
     EXIM_DBOPEN(oncelog, dirname, O_RDWR|O_CREAT, ob->mode, &dbm_file);
     if (!dbm_file)
       {
@@ -514,13 +533,14 @@ if (oncelog && *oncelog && to)
 
   if (then != 0 && (once_repeat_sec <= 0 || now - then < once_repeat_sec))
     {
+    uschar *m;
     int log_fd;
-    if (is_tainted(logfile))
+    if ((m = is_tainted2(logfile, 0, "Tainted '%s' (logfile for %s transport)"
+       " not permitted", logfile, tblock->name)))
       {
       addr->transport_return = DEFER;
       addr->basic_errno = EACCES;
-      addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)"
-       " not permitted", logfile, tblock->name);
+      addr->message = m;
       goto END_OFF;
       }
 
@@ -547,12 +567,13 @@ if (oncelog && *oncelog && to)
 /* We are going to send a message. Ensure any requested file is available. */
 if (file)
   {
-  if (is_tainted(file))
+  uschar *m;
+  if ((m = is_tainted2(file, 0, "Tainted '%s' (file for %s transport)"
+      " not permitted", file, tblock->name)))
     {
     addr->transport_return = DEFER;
     addr->basic_errno = EACCES;
-    addr->message = string_sprintf("Tainted '%s' (file for %s transport)"
-      " not permitted", file, tblock->name);
+    addr->message = m;
     return FALSE;
     }
   if (!(ff = Ufopen(file, "rb")) && !ob->file_optional)
@@ -567,12 +588,10 @@ if (file)
 
 /* Make a subprocess to send the message */
 
-pid = child_open_exim(&fd);
-
-/* Creation of child failed; defer this delivery. */
-
-if (pid < 0)
+if ((pid = child_open_exim(&fd, US"autoreply")) < 0)
   {
+  /* Creation of child failed; defer this delivery. */
+
   addr->transport_return = DEFER;
   addr->basic_errno = errno;
   addr->message = string_sprintf("Failed to create child process to send "
@@ -627,6 +646,7 @@ if (text)
 
 if (ff)
   {
+debug_printf("%s %d: ff\n", __FUNCTION__, __LINE__);
   while (Ufgets(big_buffer, big_buffer_size, ff) != NULL)
     {
     if (file_expand)
@@ -650,12 +670,12 @@ limit if we are returning the body. */
 
 if (return_message)
   {
-  uschar *rubric = (tblock->headers_only)?
-    US"------ This is a copy of the message's header lines.\n"
-    : (tblock->body_only)?
-    US"------ This is a copy of the body of the message, without the headers.\n"
-    :
-    US"------ This is a copy of the message, including all the headers.\n";
+debug_printf("%s %d: ret msg\n", __FUNCTION__, __LINE__);
+  uschar *rubric = tblock->headers_only
+    ? US"------ This is a copy of the message's header lines.\n"
+    : tblock->body_only
+    ? US"------ This is a copy of the body of the message, without the headers.\n"
+    US"------ This is a copy of the message, including all the headers.\n";
   transport_ctx tctx = {
     .u = {.fd = fileno(fp)},
     .tblock = tblock,