Add missing search_tidyup() calls for the subprocess used for running
[exim.git] / src / src / rda.c
index 66fd8745d7682d5e9e2ce34be48e45e3f60bc527..7819a8023692528d1f7cb7b701ebe4771e22bf61 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/rda.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/rda.c,v 1.9 2005/08/02 13:43:04 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2005 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* This module contains code for extracting addresses from a forwarding list
@@ -299,23 +299,17 @@ if (fread(filebuf, 1, statbuf.st_size, fwd) != statbuf.st_size)
   }
 filebuf[statbuf.st_size] = 0;
 
-/* Don't pass statbuf.st_size directly to debug_printf. On some systems it
-is a long, which may not be the same as an int. */
-
 DEBUG(D_route)
-  {
-  int size = (int)statbuf.st_size;
-  debug_printf("%d bytes read from %s\n", size, filename);
-  }
+  debug_printf(OFF_T_FMT " bytes read from %s\n", statbuf.st_size, filename);
 
-fclose(fwd);
+(void)fclose(fwd);
 return filebuf;
 
 /* Return an error: the string is already set up. */
 
 ERROR_RETURN:
 *yield = FF_ERROR;
-fclose(fwd);
+(void)fclose(fwd);
 return NULL;
 }
 
@@ -333,6 +327,8 @@ Arguments:
   options                   the options bits
   include_directory         restrain to this directory
   sieve_vacation_directory  passed to sieve_interpret
+  sieve_useraddress         passed to sieve_interpret
+  sieve_subaddress          passed to sieve_interpret
   generated                 where to hang generated addresses
   error                     for error messages
   eblockp                   for details of skipped syntax errors
@@ -348,7 +344,8 @@ Returns:                    a suitable return for rda_interpret()
 
 static int
 rda_extract(redirect_block *rdata, int options, uschar *include_directory,
-  uschar *sieve_vacation_directory, address_item **generated, uschar **error,
+  uschar *sieve_vacation_directory, uschar *sieve_useraddress,
+  uschar *sieve_subaddress, address_item **generated, uschar **error,
   error_block **eblockp, int *filtertype)
 {
 uschar *data;
@@ -374,23 +371,42 @@ if (*filtertype != FILTER_FORWARD)
   int frc;
   int old_expand_forbid = expand_forbid;
 
+  DEBUG(D_route) debug_printf("data is %s filter program\n",
+    (*filtertype == FILTER_EXIM)? "an Exim" : "a Sieve");
+
+  /* RDO_FILTER is an "allow" bit */
+
   if ((options & RDO_FILTER) == 0)
     {
     *error = US"filtering not enabled";
     return FF_ERROR;
     }
 
-  DEBUG(D_route) debug_printf("data is %s filter program\n",
-    (*filtertype == FILTER_EXIM)? "an Exim" : "a Sieve");
-
   expand_forbid =
     (expand_forbid & ~RDO_FILTER_EXPANSIONS) |
     (options & RDO_FILTER_EXPANSIONS);
 
-  frc = (*filtertype == FILTER_EXIM)?
-    filter_interpret(data, options, generated, error)
-    :
-    sieve_interpret(data, options, sieve_vacation_directory, generated, error);
+  /* RDO_{EXIM,SIEVE}_FILTER are forbid bits */
+
+  if (*filtertype == FILTER_EXIM)
+    {
+    if ((options & RDO_EXIM_FILTER) != 0)
+      {
+      *error = US"Exim filtering not enabled";
+      return FF_ERROR;
+      }
+    frc = filter_interpret(data, options, generated, error);
+    }
+  else
+    {
+    if ((options & RDO_SIEVE_FILTER) != 0)
+      {
+      *error = US"Sieve filtering not enabled";
+      return FF_ERROR;
+      }
+    frc = sieve_interpret(data, options, sieve_vacation_directory,
+      sieve_useraddress, sieve_subaddress, generated, error);
+    }
 
   expand_forbid = old_expand_forbid;
   return frc;
@@ -430,8 +446,8 @@ static void
 rda_write_string(int fd, uschar *s)
 {
 int len = (s == NULL)? 0 : Ustrlen(s) + 1;
-write(fd, &len, sizeof(int));
-if (s != NULL) write(fd, s, len);
+(void)write(fd, &len, sizeof(int));
+if (s != NULL) (void)write(fd, s, len);
 }
 
 
@@ -496,6 +512,8 @@ Arguments:
                               plus ENOTDIR and EACCES handling bits
   include_directory         restrain :include: to this directory
   sieve_vacation_directory  directory passed to sieve_interpret()
+  sieve_useraddress         passed to sieve_interpret
+  sieve_subaddress          passed to sieve_interpret
   ugid                      uid/gid to run under - if NULL, no change
   generated                 where to hang generated addresses, initially NULL
   error                     pointer for error message
@@ -522,7 +540,8 @@ Returns:        values from extraction function, or FF_NONEXIST:
 
 int
 rda_interpret(redirect_block *rdata, int options, uschar *include_directory,
-  uschar *sieve_vacation_directory, ugid_block *ugid, address_item **generated,
+  uschar *sieve_vacation_directory, uschar *sieve_useraddress,
+  uschar *sieve_subaddress, ugid_block *ugid, address_item **generated,
   uschar **error, error_block **eblockp, int *filtertype, uschar *rname)
 {
 int fd, rc, pfd[2];
@@ -567,7 +586,8 @@ if (!ugid->uid_set ||                         /* Either there's no uid, or */
      Ustrstr(data, ":include:") == NULL))     /* and there's no :include: */
   {
   return rda_extract(rdata, options, include_directory,
-    sieve_vacation_directory, generated, error, eblockp, filtertype);
+    sieve_vacation_directory, sieve_useraddress, sieve_subaddress,
+    generated, error, eblockp, filtertype);
   }
 
 /* We need to run the processing code in a sub-process. However, if we can
@@ -587,15 +607,19 @@ if (pipe(pfd) != 0)
 
 /* Ensure that SIGCHLD is set to SIG_DFL before forking, so that the child
 process can be waited for. We sometimes get here with it set otherwise. Save
-the old state for resetting on the wait. */
+the old state for resetting on the wait. Ensure that all cached resources are
+freed so that the subprocess starts with a clean slate and doesn't interfere
+with the parent process. */
 
 oldsignal = signal(SIGCHLD, SIG_DFL);
+search_tidyup();
+
 if ((pid = fork()) == 0)
   {
   header_line *waslast = header_last;   /* Save last header */
 
   fd = pfd[pipe_write];
-  close(pfd[pipe_read]);
+  (void)close(pfd[pipe_read]);
   exim_setugid(ugid->uid, ugid->gid, FALSE, rname);
 
   /* Addresses can get rewritten in filters; if we are not root or the exim
@@ -612,13 +636,14 @@ if ((pid = fork()) == 0)
   /* Now do the business */
 
   yield = rda_extract(rdata, options, include_directory,
-    sieve_vacation_directory, generated, error, eblockp, filtertype);
+    sieve_vacation_directory, sieve_useraddress, sieve_subaddress, generated,
+    error, eblockp, filtertype);
 
   /* Pass back whether it was a filter, and the return code and any overall
   error text via the pipe. */
 
-  write(fd, filtertype, sizeof(int));
-  write(fd, &yield, sizeof(int));
+  (void)write(fd, filtertype, sizeof(int));
+  (void)write(fd, &yield, sizeof(int));
   rda_write_string(fd, *error);
 
   /* Pass back the contents of any syntax error blocks if we have a pointer */
@@ -644,10 +669,10 @@ if ((pid = fork()) == 0)
     header_line *h;
     for (h = header_list; h != waslast->next; i++, h = h->next)
       {
-      if (h->type == htype_old) write(fd, &i, sizeof(i));
+      if (h->type == htype_old) (void)write(fd, &i, sizeof(i));
       }
     i = -1;
-    write(fd, &i, sizeof(i));
+    (void)write(fd, &i, sizeof(i));
 
     while (waslast != header_last)
       {
@@ -655,7 +680,7 @@ if ((pid = fork()) == 0)
       if (waslast->type != htype_old)
         {
         rda_write_string(fd, waslast->text);
-        write(fd, &(waslast->type), sizeof(waslast->type));
+        (void)write(fd, &(waslast->type), sizeof(waslast->type));
         }
       }
     rda_write_string(fd, NULL);    /* Indicates end of added headers */
@@ -663,7 +688,7 @@ if ((pid = fork()) == 0)
 
   /* Write the contents of the $n variables */
 
-  write(fd, filter_n, sizeof(filter_n));
+  (void)write(fd, filter_n, sizeof(filter_n));
 
   /* If the result was DELIVERED or NOTDELIVERED, we pass back the generated
   addresses, and their associated information, through the pipe. This is
@@ -680,8 +705,8 @@ if ((pid = fork()) == 0)
       int reply_options = 0;
 
       rda_write_string(fd, addr->address);
-      write(fd, &(addr->mode), sizeof(addr->mode));
-      write(fd, &(addr->flags), sizeof(addr->flags));
+      (void)write(fd, &(addr->mode), sizeof(addr->mode));
+      (void)write(fd, &(addr->flags), sizeof(addr->flags));
       rda_write_string(fd, addr->p.errors_address);
 
       if (addr->pipe_expandn != NULL)
@@ -693,15 +718,15 @@ if ((pid = fork()) == 0)
       rda_write_string(fd, NULL);
 
       if (addr->reply == NULL)
-        write(fd, &reply_options, sizeof(int));    /* 0 means no reply */
+        (void)write(fd, &reply_options, sizeof(int));    /* 0 means no reply */
       else
         {
         reply_options |= REPLY_EXISTS;
         if (addr->reply->file_expand) reply_options |= REPLY_EXPAND;
         if (addr->reply->return_message) reply_options |= REPLY_RETURN;
-        write(fd, &reply_options, sizeof(int));
-        write(fd, &(addr->reply->expand_forbid), sizeof(int));
-        write(fd, &(addr->reply->once_repeat), sizeof(time_t));
+        (void)write(fd, &reply_options, sizeof(int));
+        (void)write(fd, &(addr->reply->expand_forbid), sizeof(int));
+        (void)write(fd, &(addr->reply->once_repeat), sizeof(time_t));
         rda_write_string(fd, addr->reply->to);
         rda_write_string(fd, addr->reply->cc);
         rda_write_string(fd, addr->reply->bcc);
@@ -719,9 +744,11 @@ if ((pid = fork()) == 0)
     rda_write_string(fd, NULL);   /* Marks end of addresses */
     }
 
-  /* OK, this process is now done. Must use _exit() and not exit() !! */
+  /* OK, this process is now done. Free any cached resources. Must use _exit()
+  and not exit() !! */
 
-  close(fd);
+  (void)close(fd);
+  search_tidyup();
   _exit(0);
   }
 
@@ -734,7 +761,7 @@ if (pid < 0)
 writing end must be closed first, as otherwise read() won't return zero on an
 empty pipe. Afterwards, close the reading end. */
 
-close(pfd[pipe_write]);
+(void)close(pfd[pipe_write]);
 
 /* Read initial data, including yield and contents of *error */
 
@@ -919,7 +946,7 @@ else if (status != 0)
   }
 
 FINAL_EXIT:
-close(fd);
+(void)close(fd);
 signal(SIGCHLD, oldsignal);   /* restore */
 return yield;