tidying
[exim.git] / src / src / transports / pipe.c
index c1e2b26c7ccd8ba8a7d7af934df8c2ef011c28ca..f8a1427b93b789080570454ebbbb2be7f31d7096 100644 (file)
@@ -2,12 +2,15 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim maintainers 2020 - 2023 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 
 #include "../exim.h"
+
+#ifdef TRANSPORT_PIPE  /* Remainder of file */
 #include "pipe.h"
 
 #ifdef HAVE_SETCLASSRESOURCES
@@ -88,31 +91,13 @@ BOOL pipe_transport_entry(transport_instance *tblock, address_item *addr) {retur
 /* Default private options block for the pipe transport. */
 
 pipe_transport_options_block pipe_transport_option_defaults = {
-  NULL,           /* cmd */
-  NULL,           /* allow_commands */
-  NULL,           /* environment */
-  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 */
-     mac_expanded_string(EX_CANTCREAT),
-  NULL,           /* check_string */
-  NULL,           /* escape_string */
-  022,            /* umask */
-  20480,          /* max_output */
-  60*60,          /* timeout */
-  0,              /* options */
-  FALSE,          /* force_command */
-  FALSE,          /* freeze_exec_fail */
-  FALSE,          /* freeze_signal */
-  FALSE,          /* ignore_status */
-  FALSE,          /* permit_coredump */
-  FALSE,          /* restrict_to_path */
-  FALSE,          /* timeout_defer */
-  FALSE,          /* use_shell */
-  FALSE,          /* use_bsmtp */
-  FALSE,          /* use_classresources */
-  FALSE           /* use_crlf */
+  .path =      US"/bin:/usr/bin",
+  .temp_errors = US mac_expanded_string(EX_TEMPFAIL) ":"
+                  mac_expanded_string(EX_CANTCREAT),
+  .umask =     022,
+  .max_output = 20480,
+  .timeout =   60*60,
+  /* all others null/zero/false */
 };
 
 
@@ -144,13 +129,6 @@ pipe_transport_setup(transport_instance *tblock, address_item *addrlist,
 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)
   {
@@ -285,12 +263,12 @@ if (ob->allow_commands && ob->use_shell)
 driver options. Only one of body_only and headers_only can be set. */
 
 ob->options |=
-  (tblock->body_only? topt_no_headers : 0) |
-  (tblock->headers_only? topt_no_body : 0) |
-  (tblock->return_path_add? topt_add_return_path : 0) |
-  (tblock->delivery_date_add? topt_add_delivery_date : 0) |
-  (tblock->envelope_to_add? topt_add_envelope_to : 0) |
-  (ob->use_crlf? topt_use_crlf : 0);
+    (tblock->body_only ? topt_no_headers : 0)
+  | (tblock->headers_only ? topt_no_body : 0)
+  | (tblock->return_path_add ? topt_add_return_path : 0)
+  | (tblock->delivery_date_add ? topt_add_delivery_date : 0)
+  | (tblock->envelope_to_add ? topt_add_envelope_to : 0)
+  | (ob->use_crlf ? topt_use_crlf : 0);
 }
 
 
@@ -316,9 +294,9 @@ Returns:             TRUE if all went well; otherwise an error will be
 */
 
 static BOOL
-set_up_direct_command(const uschar ***argvptr, uschar *cmd,
-  BOOL expand_arguments, int expand_fail, address_item *addr, uschar *tname,
-  pipe_transport_options_block *ob)
+set_up_direct_command(const uschar *** argvptr, const uschar * cmd,
+  BOOL expand_arguments, int expand_fail, address_item * addr, uschar * tname,
+  pipe_transport_options_block * ob)
 {
 BOOL permitted = FALSE;
 const uschar **argv;
@@ -328,8 +306,9 @@ call the common function for creating an argument list and expanding
 the items if necessary. If it fails, this function fails (error information
 is in the addresses). */
 
-if (!transport_set_up_command(argvptr, cmd, expand_arguments, expand_fail,
-      addr, string_sprintf("%.50s transport", tname), NULL))
+if (!transport_set_up_command(argvptr, cmd,
+      expand_arguments ? TSUC_EXPAND_ARGS : 0,
+      expand_fail, addr, string_sprintf("%.50s transport", tname), NULL))
   return FALSE;
 
 /* Point to the set-up arguments. */
@@ -338,6 +317,7 @@ argv = *argvptr;
 
 /* If allow_commands is set, see if the command is in the permitted list. */
 
+GET_OPTION("allow_commands");
 if (ob->allow_commands)
   {
   int sep = 0;
@@ -391,10 +371,11 @@ for it. */
 if (argv[0][0] != '/')
   {
   int sep = 0;
-  uschar *p;
-  const uschar *listptr = expand_string(ob->path);
+  uschar * p;
 
-  while ((p = string_nextinlist(&listptr, &sep, NULL, 0)))
+  GET_OPTION("path");
+  for (const uschar * listptr = expand_string(ob->path);
+      p = string_nextinlist(&listptr, &sep, NULL, 0); )
     {
     struct stat statbuf;
     sprintf(CS big_buffer, "%.256s/%.256s", p, argv[0]);
@@ -437,12 +418,12 @@ Returns:             TRUE if all went well; otherwise an error will be
 */
 
 static BOOL
-set_up_shell_command(const uschar ***argvptr, uschar *cmd,
-  BOOL expand_arguments, int expand_fail, address_item *addr, uschar *tname)
+set_up_shell_command(const uschar *** argvptr, const uschar * cmd,
+  BOOL expand_arguments, int expand_fail, address_item * addr, uschar * tname)
 {
 const uschar **argv;
 
-*argvptr = argv = store_get((4)*sizeof(uschar *), FALSE);
+*argvptr = argv = store_get((4)*sizeof(uschar *), GET_UNTAINTED);
 
 argv[0] = US"/bin/sh";
 argv[1] = US"-c";
@@ -476,16 +457,19 @@ if (expand_arguments)
 
     for (address_item * ad = addr; ad; ad = ad->next)
       {
+      DEBUG(D_transport) if (is_tainted(ad->address))
+       debug_printf("tainted element '%s' from $pipe_addresses\n", ad->address);
+
       /*XXX string_append_listele() ? */
       if (ad != addr) g = string_catn(g, US" ", 1);
       g = string_cat(g, ad->address);
       }
 
     g = string_cat(g, q);
-    argv[2] = (cmd = string_from_gstring(g)) ? expand_string(cmd) : NULL;
+    argv[2] = (cmd = string_from_gstring(g)) ? expand_cstring(cmd) : NULL;
     }
   else
-    argv[2] = expand_string(cmd);
+    argv[2] = expand_cstring(cmd);
 
   f.enable_dollar_recipients = FALSE;
 
@@ -538,11 +522,12 @@ pipe_transport_options_block *ob =
 int timeout = ob->timeout;
 BOOL written_ok = FALSE;
 BOOL expand_arguments;
-const uschar **argv;
-uschar *envp[50];
-const uschar *envlist = ob->environment;
-uschar *cmd, *ss;
-uschar *eol = ob->use_crlf ? US"\r\n" : US"\n";
+const uschar ** argv;
+uschar * envp[50];
+const uschar * envlist = ob->environment;
+const uschar * cmd;
+uschar * ss;
+uschar * eol = ob->use_crlf ? US"\r\n" : US"\n";
 transport_ctx tctx = {
   .tblock = tblock,
   .addr = addr,
@@ -569,6 +554,7 @@ if (testflag(addr, af_pfr) && addr->local_part[0] == '|')
     {
     /* Enables expansion of $address_pipe into separate arguments */
     setflag(addr, af_force_command);
+    GET_OPTION("commsnd");
     cmd = ob->cmd;
     expand_arguments = TRUE;
     expand_fail = PANIC;
@@ -576,21 +562,21 @@ if (testflag(addr, af_pfr) && addr->local_part[0] == '|')
   else
     {
     cmd = addr->local_part + 1;
-    while (isspace(*cmd)) cmd++;
+    Uskip_whitespace(&cmd);
     expand_arguments = testflag(addr, af_expand_pipe);
     expand_fail = FAIL;
     }
 else
   {
+  GET_OPTION("commsnd");
   cmd = ob->cmd;
   expand_arguments = TRUE;
   expand_fail = PANIC;
   }
 
 /* If no command has been supplied, we are in trouble.
- * We also check for an empty string since it may be
- * coming from addr->local_part[0] == '|'
- */
+We also check for an empty string since it may be
+coming from addr->local_part[0] == '|' */
 
 if (!cmd || !*cmd)
   {
@@ -601,6 +587,7 @@ if (!cmd || !*cmd)
   }
 if (is_tainted(cmd))
   {
+  DEBUG(D_transport) debug_printf("cmd '%s' is tainted\n", cmd);
   addr->message = string_sprintf("Tainted '%s' (command "
     "for %s transport) not permitted", cmd, tblock->name);
   addr->transport_return = PANIC;
@@ -659,15 +646,17 @@ envp[envcount++] = string_sprintf("QUALIFY_DOMAIN=%s", qualify_domain_sender);
 envp[envcount++] = string_sprintf("SENDER=%s", sender_address);
 envp[envcount++] = US"SHELL=/bin/sh";
 
-if (addr->host_list != NULL)
+if (addr->host_list)
   envp[envcount++] = string_sprintf("HOST=%s", addr->host_list->name);
 
-if (f.timestamps_utc) envp[envcount++] = US"TZ=UTC";
-else if (timezone_string != NULL && timezone_string[0] != 0)
+if (f.timestamps_utc)
+  envp[envcount++] = US"TZ=UTC";
+else if (timezone_string && timezone_string[0])
   envp[envcount++] = string_sprintf("TZ=%s", timezone_string);
 
 /* Add any requested items */
 
+GET_OPTION("environment");
 if (envlist)
   if (!(envlist = expand_cstring(envlist)))
     {
@@ -678,7 +667,7 @@ if (envlist)
     return FALSE;
     }
 
-while ((ss = string_nextinlist(&envlist, &envsep, big_buffer, big_buffer_size)))
+while ((ss = string_nextinlist(&envlist, &envsep, NULL, 0)))
    {
    if (envcount > nelem(envp) - 2)
      {
@@ -738,7 +727,7 @@ tctx.u.fd = fd_in;
 
 /* Now fork a process to handle the output that comes down the pipe. */
 
-if ((outpid = exim_fork(US"pipe-transport output")) < 0)
+if ((outpid = exim_fork(US"pipe-tpt-output")) < 0)
   {
   addr->basic_errno = errno;
   addr->transport_return = DEFER;
@@ -814,9 +803,10 @@ transport_count = 0;
 
 /* First write any configured prefix information */
 
+GET_OPTION("message_prefix");
 if (ob->message_prefix)
   {
-  uschar *prefix = expand_string(ob->message_prefix);
+  uschar * prefix = expand_string(ob->message_prefix);
   if (!prefix)
     {
     addr->transport_return = f.search_find_defer? DEFER : PANIC;
@@ -856,9 +846,10 @@ if (!transport_write_message(&tctx, 0))
 
 /* Now any configured suffix */
 
+GET_OPTION("message_suffix");
 if (ob->message_suffix)
   {
-  uschar *suffix = expand_string(ob->message_suffix);
+  uschar * suffix = expand_string(ob->message_suffix);
   if (!suffix)
     {
     addr->transport_return = f.search_find_defer? DEFER : PANIC;
@@ -1142,4 +1133,5 @@ return FALSE;
 }
 
 #endif /*!MACRO_PREDEF*/
+#endif /*TRASPORT_PIPE*/
 /* End of transport/pipe.c */