Add option to control use of shutdown by ${readsocket }. Bug 400
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 26 Feb 2017 18:53:06 +0000 (18:53 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 26 Feb 2017 19:01:07 +0000 (19:01 +0000)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/expand.c
test/scripts/0000-Basic/0373
test/stdout/0373

index 8b20910..054a135 100644 (file)
@@ -9767,7 +9767,7 @@ locks out the use of this expansion item in filter files.
 
 
 .vitem "&*${readsocket{*&<&'name'&>&*}{*&<&'request'&>&*}&&&
-        {*&<&'timeout'&>&*}{*&<&'eol&~string'&>&*}{*&<&'fail&~string'&>&*}}*&"
+        {*&<&'options'&>&*}{*&<&'eol&~string'&>&*}{*&<&'fail&~string'&>&*}}*&"
 .cindex "expansion" "inserting from a socket"
 .cindex "socket, use of in expansion"
 .cindex "&%readsocket%& expansion item"
@@ -9797,6 +9797,17 @@ extend what can be done. Firstly, you can vary the timeout. For example:
 .code
 ${readsocket{/socket/name}{request string}{3s}}
 .endd
+.new
+The third argument is a list of options, of which the first element is the timeout
+and must be present if the argument is given.
+Further elements are options of form &'name=value'&.
+One option type is currently recognised, defining whether (the default)
+or not a shutdown is done on the connection after sending the request.
+Example, to not do so (preferred, eg. by some webservers):
+.code
+${readsocket{/socket/name}{request string}{3s:shutdown=no}}
+.endd
+.wen
 A fourth argument allows you to change any newlines that are in the data
 that is read, in the same way as for &%readfile%& (see above). This example
 turns them into spaces:
index 2a8e520..efb8592 100644 (file)
@@ -12,6 +12,9 @@ Version 4.90
  1. PKG_CONFIG_PATH can now be set in Local/Makefile;
     wildcards will be expanded, values are collapsed.
 
+ 2. The ${readsocket } expansion now takes an option to not shutdown the
+    connection after sending the query string.  The default remains to do so.
+
 
 Version 4.89
 ------------
index f85ee49..1da8589 100644 (file)
@@ -4726,8 +4726,9 @@ while (*s != 0)
       struct sockaddr_un sockun;         /* don't call this "sun" ! */
       uschar *arg;
       uschar *sub_arg[4];
+      BOOL do_shutdown = TRUE;
 
-      if ((expand_forbid & RDO_READSOCK) != 0)
+      if (expand_forbid & RDO_READSOCK)
         {
         expand_string_message = US"socket insertions are not permitted";
         goto EXPAND_FAILED;
@@ -4743,17 +4744,27 @@ while (*s != 0)
         case 3: goto EXPAND_FAILED;
         }
 
-      /* Sort out timeout, if given */
+      /* Sort out timeout, if given.  The second arg is a list with the first element
+      being a time value.  Any more are options of form "name=value".  Currently the
+      only option recognised is "shutdown". */
 
-      if (sub_arg[2] != NULL)
+      if (sub_arg[2])
         {
-        timeout = readconf_readtime(sub_arg[2], 0, FALSE);
-        if (timeout < 0)
+       const uschar * list = sub_arg[2];
+       uschar * item;
+       int sep = 0;
+
+       item = string_nextinlist(&list, &sep, NULL, 0);
+        if ((timeout = readconf_readtime(item, 0, FALSE)) < 0)
           {
-          expand_string_message = string_sprintf("bad time value %s",
-            sub_arg[2]);
+          expand_string_message = string_sprintf("bad time value %s", item);
           goto EXPAND_FAILED;
           }
+
+       while ((item = string_nextinlist(&list, &sep, NULL, 0)))
+         if (Ustrncmp(item, US"shutdown=", 9) == 0)
+           if (Ustrcmp(item + 9, US"no") == 0)
+             do_shutdown = FALSE;
         }
       else sub_arg[3] = NULL;                     /* No eol if no timeout */
 
@@ -4867,9 +4878,9 @@ while (*s != 0)
         recognise that it is their turn to do some work. Just in case some
         system doesn't have this function, make it conditional. */
 
-        #ifdef SHUT_WR
-        shutdown(fd, SHUT_WR);
-        #endif
+#ifdef SHUT_WR
+       if (do_shutdown) shutdown(fd, SHUT_WR);
+#endif
 
        if (running_in_test_harness) millisleep(100);
 
@@ -4909,7 +4920,7 @@ while (*s != 0)
         while (isspace(*s)) s++;
         }
 
-    readsock_done:
+    READSOCK_DONE:
       if (*s++ != '}')
         {
        expand_string_message = US"missing '}' closing readsocket";
@@ -4921,7 +4932,7 @@ while (*s != 0)
       socket, or timeout on reading. If another substring follows, expand and
       use it. Otherwise, those conditions give expand errors. */
 
-      SOCK_FAIL:
+    SOCK_FAIL:
       if (*s != '{') goto EXPAND_FAILED;
       DEBUG(D_any) debug_printf("%s\n", expand_string_message);
       if (!(arg = expand_string_internal(s+1, TRUE, &s, FALSE, TRUE, &resetok)))
@@ -4933,7 +4944,7 @@ while (*s != 0)
        goto EXPAND_FAILED_CURLY;
        }
       while (isspace(*s)) s++;
-      goto readsock_done;
+      goto READSOCK_DONE;
       }
 
     /* Handle "run" to execute a program. */
index d5e2cb1..02cdc31 100644 (file)
@@ -58,7 +58,7 @@ quit
 #
 # Tests of IPv4 sockets
 #
-server PORT_S 10
+server PORT_S 11
 QUERY-1
 >LF>ANSWER-1
 >*eof
@@ -85,6 +85,8 @@ QUERY-9
 QUERY-10
 >LF>ANSWER-10
 >*eof
+>LF>ANSWER-11
+>*eof
 ****
 millisleep 500
 exim -be
@@ -98,4 +100,5 @@ exim -be
 8 >>${readsocket{inet:127.0.0.1:PORT_S}{QUERY-8\n}{1s}}<<
 9 >>${readsocket{inet:127.0.0.1:PORT_S}{QUERY-9\n}{1s}{}{sock error}}<<
 10 >>${readsocket{inet:badloop:PORT_S}{QUERY-10\n}}<<
+11 >>${readsocket{inet:thisloop:PORT_S}{QUERY-11\n}{2s:shutdown=no}}<<
 ****
index 88592ff..b6f6f19 100644 (file)
@@ -25,6 +25,8 @@
 > 9 >>sock error<<
 > 10 >>ANSWER-10
 <<
+> 11 >>ANSWER-11
+<<
 > 
 
 ******** SERVER ********
@@ -120,4 +122,8 @@ Connection request from [127.0.0.1]
 QUERY-10
 >LF>ANSWER-10
 >*eof
+Listening on port 1224 ... 
+Connection request from [ip4.ip4.ip4.ip4]
+>LF>ANSWER-11
+>*eof
 End of script