Add permit_coredump pipe transport option. Fixes: #834
[exim.git] / src / src / transports / pipe.c
index 97d69db0feb64a3653f3412c971fa8aa6309e55a..2464abd14a6af5b6a75b6829ca6405cf524ef542 100644 (file)
@@ -1,17 +1,17 @@
-/* $Cambridge: exim/src/src/transports/pipe.c,v 1.10 2006/02/21 16:24:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/pipe.c,v 1.15 2010/06/05 10:04:44 pdp Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
 #include "../exim.h"
 #include "pipe.h"
 
-#ifdef HAVE_LOGIN_CAP
+#ifdef HAVE_SETCLASSRESOURCES
 #include <login_cap.h>
 #endif
 
@@ -57,6 +57,8 @@ optionlist pipe_transport_options[] = {
       (void *)offsetof(pipe_transport_options_block, message_suffix) },
   { "path",              opt_stringptr,
       (void *)offsetof(pipe_transport_options_block, path) },
+  { "permit_coredump",   opt_bool,
+      (void *)offsetof(pipe_transport_options_block, permit_coredump) },
   { "pipe_as_creator",   opt_bool | opt_public,
       (void *)offsetof(transport_instance, deliver_as_creator) },
   { "restrict_to_path",  opt_bool,
@@ -75,7 +77,7 @@ optionlist pipe_transport_options[] = {
       (void *)offsetof(pipe_transport_options_block, umask) },
   { "use_bsmtp",         opt_bool,
       (void *)offsetof(pipe_transport_options_block, use_bsmtp) },
-  #ifdef HAVE_LOGIN_CAP
+  #ifdef HAVE_SETCLASSRESOURCES
   { "use_classresources", opt_bool,
       (void *)offsetof(pipe_transport_options_block, use_classresources) },
   #endif
@@ -110,6 +112,7 @@ pipe_transport_options_block pipe_transport_option_defaults = {
   0,              /* options */
   FALSE,          /* freeze_exec_fail */
   FALSE,          /* ignore_status */
+  FALSE,          /* permit_coredump */
   FALSE,          /* restrict_to_path */
   FALSE,          /* timeout_defer */
   FALSE,          /* use_shell */
@@ -127,7 +130,7 @@ pipe_transport_options_block pipe_transport_option_defaults = {
 /* Called for each delivery in the privileged state, just before the uid/gid
 are changed and the main entry point is called. In a system that supports the
 login_cap facilities, this function is used to set the class resource limits
-for the user.
+for the user.  It may also re-enable coredumps.
 
 Arguments:
   tblock     points to the transport instance
@@ -154,7 +157,7 @@ gid = gid;
 errmsg = errmsg;
 ob = ob;
 
-#ifdef HAVE_LOGIN_CAP
+#ifdef HAVE_SETCLASSRESOURCES
 if (ob->use_classresources)
   {
   struct passwd *pw = getpwuid(uid);
@@ -170,6 +173,24 @@ if (ob->use_classresources)
   }
 #endif
 
+#ifdef RLIMIT_CORE
+if (ob->permit_coredump)
+  {
+  struct rlimit rl;
+  rl.rlim_cur = RLIM_INFINITY;
+  rl.rlim_max = RLIM_INFINITY;
+  if (setrlimit(RLIMIT_CORE, &rl) < 0)
+    {
+#ifdef SETRLIMIT_NOT_SUPPORTED
+    if (errno != ENOSYS && errno != ENOTSUP)
+#endif
+      log_write(0, LOG_MAIN,
+          "delivery setrlimit(RLIMIT_CORE, RLIMI_INFINITY) failed: %s",
+          strerror(errno));
+    }
+  }
+#endif
+
 return OK;
 }
 
@@ -924,6 +945,18 @@ if ((rc = child_close(pid, timeout)) != 0)
       "transport: %s%s", tblock->name, strerror(errno), tmsg);
     }
 
+  /* Since the transport_filter timed out we assume it has sent the child process
+  a malformed or incomplete data stream.  Kill off the child process
+  and prevent checking its exit status as it will has probably exited in error.
+  This prevents the transport_filter timeout message from getting overwritten
+  by the exit error which is not the cause of the problem. */
+
+  else if (transport_filter_timed_out)
+    {
+    killpg(pid, SIGKILL);
+    kill(outpid, SIGKILL);
+    }
+
   /* Either the process completed, but yielded a non-zero (necessarily
   positive) status, or the process was terminated by a signal (rc will contain
   the negation of the signal number). Treat killing by signal as failure unless