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; }