summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuck Short <zul@gentoo.org>2004-05-16 14:10:49 +0000
committerChuck Short <zul@gentoo.org>2004-05-16 14:10:49 +0000
commitc84d11c3bf108d51d706ef4e5fd067cb12a1768b (patch)
tree47af70391e5bdd9d910f6574bed7175be9b0089b /net-www/apache/files
parentAdded ~mips keyword. (Manifest recommit) (diff)
downloadgentoo-2-c84d11c3bf108d51d706ef4e5fd067cb12a1768b.tar.gz
gentoo-2-c84d11c3bf108d51d706ef4e5fd067cb12a1768b.tar.bz2
gentoo-2-c84d11c3bf108d51d706ef4e5fd067cb12a1768b.zip
Added patch for mod_cgi.
Diffstat (limited to 'net-www/apache/files')
-rw-r--r--net-www/apache/files/httpd-2.0.49-cgi.patch322
1 files changed, 322 insertions, 0 deletions
diff --git a/net-www/apache/files/httpd-2.0.49-cgi.patch b/net-www/apache/files/httpd-2.0.49-cgi.patch
new file mode 100644
index 000000000000..023fd428d8bf
--- /dev/null
+++ b/net-www/apache/files/httpd-2.0.49-cgi.patch
@@ -0,0 +1,322 @@
+diff -Naur httpd-2.0.49/modules/generators/mod_cgi.c httpd-2.0.49-gentoo/modules/generators/mod_cgi.c
+--- httpd-2.0.49/modules/generators/mod_cgi.c 2004-02-09 20:53:17.000000000 +0000
++++ httpd-2.0.49-gentoo/modules/generators/mod_cgi.c 2004-05-17 17:43:52.871026864 +0000
+@@ -32,6 +32,7 @@
+ #include "apr_optional.h"
+ #include "apr_buckets.h"
+ #include "apr_lib.h"
++#include "apr_poll.h"
+
+ #define APR_WANT_STRFUNC
+ #include "apr_want.h"
+@@ -191,13 +192,14 @@
+
+ /* Soak up stderr from a script and redirect it to the error log.
+ */
+-static void log_script_err(request_rec *r, apr_file_t *script_err)
++static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err)
+ {
+ char argsbuffer[HUGE_STRING_LEN];
+ char *newline;
++ apr_status_t rv;
+
+- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+- script_err) == APR_SUCCESS) {
++ while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
++ script_err)) == APR_SUCCESS) {
+ newline = strchr(argsbuffer, '\n');
+ if (newline) {
+ *newline = '\0';
+@@ -205,6 +207,8 @@
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "%s", argsbuffer);
+ }
++
++ return rv;
+ }
+
+ static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
+@@ -539,6 +543,172 @@
+ }
+ }
+
++#if APR_FILES_AS_SOCKETS
++
++/* A CGI bucket type is needed to catch any output to stderr from the
++ * script; see PR 22030. */
++static const apr_bucket_type_t bucket_type_cgi;
++
++struct cgi_bucket_data {
++ apr_pollset_t *pollset;
++ request_rec *r;
++};
++
++/* Create a CGI bucket using pipes from script stdout 'out'
++ * and stderr 'err', for request 'r'. */
++static apr_bucket *cgi_bucket_create(request_rec *r,
++ apr_file_t *out, apr_file_t *err,
++ apr_bucket_alloc_t *list)
++{
++ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
++ apr_status_t rv;
++ apr_pollfd_t fd;
++ struct cgi_bucket_data *data = apr_palloc(r->pool, sizeof *data);
++
++ APR_BUCKET_INIT(b);
++ b->free = apr_bucket_free;
++ b->list = list;
++ b->type = &bucket_type_cgi;
++ b->length = (apr_size_t)(-1);
++ b->start = -1;
++
++ /* Create the pollset */
++ rv = apr_pollset_create(&data->pollset, 2, r->pool, 0);
++ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
++
++ fd.desc_type = APR_POLL_FILE;
++ fd.reqevents = APR_POLLIN;
++ fd.p = r->pool;
++ fd.desc.f = out; /* script's stdout */
++ fd.client_data = (void *)1;
++ rv = apr_pollset_add(data->pollset, &fd);
++ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
++
++ fd.desc.f = err; /* script's stderr */
++ fd.client_data = (void *)2;
++ rv = apr_pollset_add(data->pollset, &fd);
++ AP_DEBUG_ASSERT(rv == APR_SUCCESS);
++
++ data->r = r;
++ b->data = data;
++ return b;
++}
++
++/* Create a duplicate CGI bucket using given bucket data */
++static apr_bucket *cgi_bucket_dup(struct cgi_bucket_data *data,
++ apr_bucket_alloc_t *list)
++{
++ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
++ APR_BUCKET_INIT(b);
++ b->free = apr_bucket_free;
++ b->list = list;
++ b->type = &bucket_type_cgi;
++ b->length = (apr_size_t)(-1);
++ b->start = -1;
++ b->data = data;
++ return b;
++}
++
++/* Handle stdout from CGI child. Duplicate of logic from the _read
++ * method of the real APR pipe bucket implementation. */
++static apr_status_t cgi_read_stdout(apr_bucket *a, apr_file_t *out,
++ const char **str, apr_size_t *len)
++{
++ char *buf;
++ apr_status_t rv;
++
++ *str = NULL;
++ *len = APR_BUCKET_BUFF_SIZE;
++ buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
++
++ rv = apr_file_read(out, buf, len);
++
++ if (rv != APR_SUCCESS && rv != APR_EOF) {
++ apr_bucket_free(buf);
++ return rv;
++ }
++
++ if (*len > 0) {
++ struct cgi_bucket_data *data = a->data;
++ apr_bucket_heap *h;
++
++ /* Change the current bucket to refer to what we read */
++ a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
++ h = a->data;
++ h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
++ *str = buf;
++ APR_BUCKET_INSERT_AFTER(a, cgi_bucket_dup(data, a->list));
++ }
++ else {
++ apr_bucket_free(buf);
++ a = apr_bucket_immortal_make(a, "", 0);
++ *str = a->data;
++ }
++ return rv;
++}
++
++/* Read method of CGI bucket: polls on stderr and stdout of the child,
++ * sending any stderr output immediately away to the error log. */
++static apr_status_t cgi_bucket_read(apr_bucket *b, const char **str,
++ apr_size_t *len, apr_read_type_e block)
++{
++ struct cgi_bucket_data *data = b->data;
++ apr_interval_time_t timeout;
++ apr_status_t rv;
++ int gotdata = 0;
++
++ timeout = block == APR_NONBLOCK_READ ? 0 : data->r->server->timeout;
++
++ do {
++ const apr_pollfd_t *results;
++ apr_int32_t num;
++
++ rv = apr_pollset_poll(data->pollset, timeout, &num, &results);
++ if (APR_STATUS_IS_TIMEUP(rv)) {
++ return timeout == 0 ? APR_EAGAIN : rv;
++ }
++ else if (APR_STATUS_IS_EINTR(rv)) {
++ continue;
++ }
++ else if (rv != APR_SUCCESS) {
++ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, data->r,
++ "poll failed waiting for CGI child");
++ return rv;
++ }
++
++ for (; num; num--, results++) {
++ if (results[0].client_data == (void *)1) {
++ /* stdout */
++ rv = cgi_read_stdout(b, results[0].desc.f, str, len);
++ if (APR_STATUS_IS_EOF(rv)) {
++ rv = APR_SUCCESS;
++ }
++ gotdata = 1;
++ } else {
++ /* stderr */
++ apr_status_t rv2 = log_script_err(data->r, results[0].desc.f);
++ if (APR_STATUS_IS_EOF(rv2)) {
++ apr_pollset_remove(data->pollset, &results[0]);
++ }
++ }
++ }
++
++ } while (!gotdata);
++
++ return rv;
++}
++
++static const apr_bucket_type_t bucket_type_cgi = {
++ "CGI", 5, APR_BUCKET_DATA,
++ apr_bucket_destroy_noop,
++ cgi_bucket_read,
++ apr_bucket_setaside_notimpl,
++ apr_bucket_split_notimpl,
++ apr_bucket_copy_notimpl
++};
++
++#endif
++
+ static int cgi_handler(request_rec *r)
+ {
+ int nph;
+@@ -556,6 +726,7 @@
+ cgi_server_conf *conf;
+ apr_status_t rv;
+ cgi_exec_info_t e_info;
++ conn_rec *c = r->connection;
+
+ if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script"))
+ return DECLINED;
+@@ -637,7 +808,7 @@
+ /* Transfer any put/post args, CERN style...
+ * Note that we already ignore SIGPIPE in the core server.
+ */
+- bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
++ bb = apr_brigade_create(r->pool, c->bucket_alloc);
+ seen_eos = 0;
+ child_stopped_reading = 0;
+ if (conf->logname) {
+@@ -710,18 +881,28 @@
+ apr_file_flush(script_out);
+ apr_file_close(script_out);
+
++ AP_DEBUG_ASSERT(script_in != NULL);
++
++ apr_brigade_cleanup(bb);
++
++#if APR_FILES_AS_SOCKETS
++ apr_file_pipe_timeout_set(script_in, 0);
++ apr_file_pipe_timeout_set(script_err, 0);
++
++ b = cgi_bucket_create(r, script_in, script_err, c->bucket_alloc);
++#else
++ b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
++#endif
++ APR_BRIGADE_INSERT_TAIL(bb, b);
++ b = apr_bucket_eos_create(c->bucket_alloc);
++ APR_BRIGADE_INSERT_TAIL(bb, b);
++
+ /* Handle script return... */
+- if (script_in && !nph) {
+- conn_rec *c = r->connection;
++ if (!nph) {
+ const char *location;
+ char sbuf[MAX_STRING_LEN];
+ int ret;
+
+- b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
+- APR_BRIGADE_INSERT_TAIL(bb, b);
+- b = apr_bucket_eos_create(c->bucket_alloc);
+- APR_BRIGADE_INSERT_TAIL(bb, b);
+-
+ if ((ret = ap_scan_script_header_err_brigade(r, bb, sbuf))) {
+ return log_script(r, conf, ret, dbuf, sbuf, bb, script_err);
+ }
+@@ -731,6 +912,7 @@
+ if (location && location[0] == '/' && r->status == 200) {
+ discard_script_output(bb);
+ apr_brigade_destroy(bb);
++ apr_file_pipe_timeout_set(script_err, r->server->timeout);
+ log_script_err(r, script_err);
+ /* This redirect needs to be a GET no matter what the original
+ * method was.
+@@ -757,22 +939,8 @@
+ }
+
+ rv = ap_pass_brigade(r->output_filters, bb);
+-
+- /* don't soak up script output if errors occurred
+- * writing it out... otherwise, we prolong the
+- * life of the script when the connection drops
+- * or we stopped sending output for some other
+- * reason
+- */
+- if (rv == APR_SUCCESS && !r->connection->aborted) {
+- log_script_err(r, script_err);
+- }
+-
+- apr_file_close(script_err);
+ }
+-
+- if (script_in && nph) {
+- conn_rec *c = r->connection;
++ else /* nph */ {
+ struct ap_filter_t *cur;
+
+ /* get rid of all filters up through protocol... since we
+@@ -786,13 +954,19 @@
+ }
+ r->output_filters = r->proto_output_filters = cur;
+
+- bb = apr_brigade_create(r->pool, c->bucket_alloc);
+- b = apr_bucket_pipe_create(script_in, c->bucket_alloc);
+- APR_BRIGADE_INSERT_TAIL(bb, b);
+- b = apr_bucket_eos_create(c->bucket_alloc);
+- APR_BRIGADE_INSERT_TAIL(bb, b);
+- ap_pass_brigade(r->output_filters, bb);
++ rv = ap_pass_brigade(r->output_filters, bb);
++ }
++
++ /* don't soak up script output if errors occurred writing it
++ * out... otherwise, we prolong the life of the script when the
++ * connection drops or we stopped sending output for some other
++ * reason */
++ if (rv == APR_SUCCESS && !r->connection->aborted) {
++ apr_file_pipe_timeout_set(script_err, r->server->timeout);
++ log_script_err(r, script_err);
+ }
++
++ apr_file_close(script_err);
+
+ return OK; /* NOT r->status, even if it has changed. */
+ }