Update version number and copyright year.
[exim.git] / src / src / transports / pipe.c
index 6fbadfb46aa7c646c2329490b4b9e742a177391b..3021194aed68e8d3687eec2bbaac741a17029098 100644 (file)
@@ -1,16 +1,20 @@
-/* $Cambridge: exim/src/src/transports/pipe.c,v 1.6 2005/05/10 11:13:09 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/pipe.c,v 1.12 2007/01/08 10:50:20 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
 #include "../exim.h"
 #include "pipe.h"
 
+#ifdef HAVE_SETCLASSRESOURCES
+#include <login_cap.h>
+#endif
+
 
 
 /* Options specific to the pipe transport. They must be in alphabetic
@@ -71,6 +75,10 @@ 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_SETCLASSRESOURCES
+  { "use_classresources", opt_bool,
+      (void *)offsetof(pipe_transport_options_block, use_classresources) },
+  #endif
   { "use_crlf",          opt_bool,
       (void *)offsetof(pipe_transport_options_block, use_crlf) },
   { "use_shell",         opt_bool,
@@ -89,7 +97,7 @@ pipe_transport_options_block pipe_transport_option_defaults = {
   NULL,           /* cmd */
   NULL,           /* allow_commands */
   NULL,           /* environment */
-  US"/usr/bin",   /* path */
+  US"/bin:/usr/bin",  /* path */
   NULL,           /* message_prefix (reset in init if not bsmtp) */
   NULL,           /* message_suffix (ditto) */
   US mac_expanded_string(EX_TEMPFAIL) ":"    /* temp_errors */
@@ -106,11 +114,67 @@ pipe_transport_options_block pipe_transport_option_defaults = {
   FALSE,          /* timeout_defer */
   FALSE,          /* use_shell */
   FALSE,          /* use_bsmtp */
+  FALSE,          /* use_classresources */
   FALSE           /* use_crlf */
 };
 
 
 
+/*************************************************
+*              Setup entry point                 *
+*************************************************/
+
+/* 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.
+
+Arguments:
+  tblock     points to the transport instance
+  addrlist   addresses about to be delivered (not used)
+  dummy      not used (doesn't pass back data)
+  uid        the uid that will be set (not used)
+  gid        the gid that will be set (not used)
+  errmsg     where to put an error message
+
+Returns:     OK, FAIL, or DEFER
+*/
+
+static int
+pipe_transport_setup(transport_instance *tblock, address_item *addrlist,
+  transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
+{
+pipe_transport_options_block *ob =
+  (pipe_transport_options_block *)(tblock->options_block);
+
+addrlist = addrlist;  /* Keep compiler happy */
+dummy = dummy;
+uid = uid;
+gid = gid;
+errmsg = errmsg;
+ob = ob;
+
+#ifdef HAVE_SETCLASSRESOURCES
+if (ob->use_classresources)
+  {
+  struct passwd *pw = getpwuid(uid);
+  if (pw != NULL)
+    {
+    login_cap_t *lc = login_getpwclass(pw);
+    if (lc != NULL)
+      {
+      setclassresources(lc);
+      login_close(lc);
+      }
+    }
+  }
+#endif
+
+return OK;
+}
+
+
+
 /*************************************************
 *          Initialization entry point            *
 *************************************************/
@@ -125,6 +189,10 @@ pipe_transport_init(transport_instance *tblock)
 pipe_transport_options_block *ob =
   (pipe_transport_options_block *)(tblock->options_block);
 
+/* Set up the setup entry point, to be called in the privileged state */
+
+tblock->setup = pipe_transport_setup;
+
 /* If pipe_as_creator is set, then uid/gid should not be set. */
 
 if (tblock->deliver_as_creator && (tblock->uid_set || tblock->gid_set ||
@@ -640,8 +708,8 @@ if ((outpid = fork()) < 0)
   addr->message = string_sprintf(
     "Failed to create process for handling output in %s transport",
       tblock->name);
-  close(fd_in);
-  close(fd_out);
+  (void)close(fd_in);
+  (void)close(fd_out);
   return FALSE;
   }
 
@@ -654,7 +722,7 @@ the subprocess to fail. */
 if (outpid == 0)
   {
   int count = 0;
-  close(fd_in);
+  (void)close(fd_in);
   set_process_info("reading output from |%s", cmd);
   while ((rc = read(fd_out, big_buffer, big_buffer_size)) > 0)
     {
@@ -671,11 +739,11 @@ if (outpid == 0)
       break;
       }
     }
-  close(fd_out);
+  (void)close(fd_out);
   _exit(0);
   }
 
-close(fd_out);  /* Not used in this process */
+(void)close(fd_out);  /* Not used in this process */
 
 
 /* Carrying on now with the main parent process. Attempt to write the message