This is responsescript patch, but this time written around APR poll API. I'm
not sure if I have got everything right, so APR gurus are welcome to take a
look. I have tested this against a bunch of web pages, and didn't see any
problem though.
regards,
Jacek Prucia
diff -urN flood.orig/config.h.in flood/config.h.in
--- flood.orig/config.h.in 2003-08-24 12:22:04.000000000 +0200
+++ flood/config.h.in 2003-08-24 12:31:22.000000000 +0200
@@ -23,6 +23,7 @@
#define XML_URLLIST_PAYLOAD_TEMPLATE "payloadtemplate"
#define XML_URLLIST_REQUEST_TEMPLATE "requesttemplate"
#define XML_URLLIST_RESPONSE_TEMPLATE "responsetemplate"
+#define XML_URLLIST_RESPONSE_SCRIPT "responsescript"
#define XML_URLLIST_RESPONSE_NAME "responsename"
#define XML_URLLIST_PROXY "proxy"
#define XML_URLLIST_PREDELAY "predelay"
diff -urN flood.orig/flood_round_robin.c flood/flood_round_robin.c
--- flood.orig/flood_round_robin.c 2003-08-24 12:22:04.000000000 +0200
+++ flood/flood_round_robin.c 2003-08-24 15:26:48.000000000 +0200
@@ -61,6 +61,8 @@
#include <apr_lib.h>
#include <apr_hash.h>
#include <apr_base64.h>
+#include <apr_poll.h>
+#include <apr_thread_proc.h>
#if APR_HAVE_STRINGS_H
#include <strings.h> /* strncasecmp */
@@ -114,6 +116,7 @@
char *payloadtemplate;
char *requesttemplate;
char *responsetemplate;
+ char *responsescript;
char *responsename;
int responselen;
char *user;
@@ -496,6 +499,11 @@
url->responsetemplate = (char*)attr->value;
}
else if (strncasecmp(attr->name,
+ XML_URLLIST_RESPONSE_SCRIPT,
+ FLOOD_STRLEN_MAX) == 0) {
+ url->responsescript = (char*)attr->value;
+ }
+ else if (strncasecmp(attr->name,
XML_URLLIST_RESPONSE_NAME,
FLOOD_STRLEN_MAX) == 0) {
url->responsename = (char*)attr->value;
@@ -952,6 +960,123 @@
rp->url[rp->current_url].responselen, newValue);
regfree(&re);
}
+ if (rp->url[rp->current_url].responsescript)
+ {
+ int exitcode = 0;
+ apr_status_t rv;
+ apr_proc_t *proc;
+ apr_pollfd_t pipeout;
+ apr_pollset_t *pollset;
+ apr_procattr_t *procattr;
+ apr_size_t nbytes, wbytes;
+
+ char **args;
+ const char *progname;
+
+
+ if (apr_procattr_create(&procattr, rp->pool) != APR_SUCCESS) {
+ apr_file_printf(local_stderr,
+ "apr_procattr_create failed for '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ if (apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_NO_PIPE,
+ APR_NO_PIPE) != APR_SUCCESS) {
+ apr_file_printf(local_stderr,
+ "apr_procattr_io_set failed for '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ if (apr_procattr_error_check_set(procattr, 1)) {
+ apr_file_printf(local_stderr,
+ "apr_procattr_error_check_set failed for '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ apr_tokenize_to_argv(rp->url[rp->current_url].responsescript, &args,
+ rp->pool);
+ progname = apr_pstrdup(rp->pool, args[0]);
+
+ proc = (apr_proc_t *)apr_pcalloc(rp->pool, sizeof(*proc));
+
+ /* create process */
+ if (apr_proc_create(proc, progname, (const char * const *)args, NULL,
+ procattr, rp->pool) != APR_SUCCESS) {
+ apr_file_printf(local_stderr,
+ "Can't spawn postprocess script '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ if (apr_file_pipe_timeout_set(proc->in, apr_time_from_sec(10))
+ != APR_SUCCESS) {
+ apr_file_printf(local_stderr,
+ "apr_file_pipe_timeout_set failed for '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ apr_pollset_create(&pollset, 1, rp->pool, 0);
+
+ pipeout.desc_type = APR_POLL_FILE;
+ pipeout.reqevents = APR_POLLOUT;
+ pipeout.desc.f = proc->in;
+ pipeout.client_data = NULL;
+
+ apr_pollset_add(pollset, &pipeout);
+
+ wbytes = 0;
+ nbytes = strlen(resp->rbuf);
+
+ while (wbytes < nbytes) {
+
+ int bytes;
+ apr_int32_t nrdes;
+ const apr_pollfd_t *ardes = NULL;
+
+ apr_pollset_poll(pollset, apr_time_from_sec(10), &nrdes, &ardes);
+
+ if (!nrdes) {
+ apr_file_printf(local_stderr,
+ "timeout writing data to script '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ /* there can be only one descriptor... */
+ const apr_pollfd_t *rdes = &(ardes[0]);
+
+ bytes = nbytes;
+ apr_file_write(rdes->desc.f, resp->rbuf, &bytes);
+
+ wbytes += bytes;
+
+ }
+
+ apr_pollset_remove(pollset, &pipeout);
+ apr_file_close(proc->in);
+
+ rv = apr_proc_wait(proc, &exitcode, NULL, APR_WAIT);
+
+ /* child may be gone already... */
+ if (!rv & (APR_CHILD_DONE | APR_SUCCESS)) {
+ apr_file_printf(local_stderr,
+ "apr_proc_wait failed for '%s'\n",
+ rp->url[rp->current_url].responsescript);
+ return APR_EGENERAL;
+ }
+
+ if (exitcode != 0) {
+ apr_file_printf(local_stderr,
+ "Postprocess script '%s' failed, exit code '%i'\n",
+ rp->url[rp->current_url].responsescript, exitcode);
+ return APR_EGENERAL;
+ }
+
+ }
return APR_SUCCESS;
}