diff options
author | Chuck Short <zul@gentoo.org> | 2004-05-16 14:10:49 +0000 |
---|---|---|
committer | Chuck Short <zul@gentoo.org> | 2004-05-16 14:10:49 +0000 |
commit | c84d11c3bf108d51d706ef4e5fd067cb12a1768b (patch) | |
tree | 47af70391e5bdd9d910f6574bed7175be9b0089b /net-www/apache/files | |
parent | Added ~mips keyword. (Manifest recommit) (diff) | |
download | gentoo-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.patch | 322 |
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. */ + } |