summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2.0/init/apache2.confd19
-rwxr-xr-x2.0/init/apache2.initd112
-rw-r--r--2.0/patches/01_all_gentoo_base.patch51
-rw-r--r--2.0/patches/03_all_gentoo-apache-tools.patch68
-rw-r--r--2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch332
-rw-r--r--2.0/patches/80_all_CVE-2007-5752.patch42
-rw-r--r--2.0/patches/81_all_CVE-2007-3304.patch16
-rw-r--r--2.0/patches/82_all_CVE-2007-1863.patch75
-rw-r--r--2.0/patches/83_all_CVE-2007-2874.patch88
-rw-r--r--2.2/conf/apache2-builtin-mods4
-rw-r--r--2.2/patches/04_all_mod_dbd_r553563.patch1279
-rw-r--r--2.2/patches/20_all_peruser_0.2.2.patch (renamed from 2.2/patches/20_all_peruser_0.2.1.patch)160
-rw-r--r--2.2/patches/21_all_itk_20070425-00.patch18
-rw-r--r--2.2/patches/80_all_CVE-2006-5752.patch40
-rw-r--r--2.2/patches/81_all_CVE-2007-1862.patch51
-rw-r--r--2.2/patches/82_all_CVE-2007-1863.patch74
-rw-r--r--2.2/patches/83_all_CVE-2007-3304.patch261
17 files changed, 276 insertions, 2414 deletions
diff --git a/2.0/init/apache2.confd b/2.0/init/apache2.confd
index 0b5b028..a272d73 100644
--- a/2.0/init/apache2.confd
+++ b/2.0/init/apache2.confd
@@ -37,9 +37,16 @@ APACHE2_OPTS="-D DEFAULT_VHOST"
# They are normally dumped to your terminal.
#STARTUPERRORLOG="/var/log/apache2/startuperror.log"
-# Environment variables to keep
-# All environment variables are cleared from apache
-# Use this to preserve some of them
-# NOTE!!! It's very important that this contains PATH
-# TODO: Phase this out in favor of /etc/conf.d/env_whitelist
-#KEEPENV="PATH"
+# A command that outputs a formatted text version of the HTML at the URL
+# of the command line. Designed for lynx, however other programs may work.
+#LYNX="lynx -dump"
+
+# The URL to your server's mod_status status page.
+# Required for status and fullstatus
+#STATUSURL="http://localhost/server-status"
+
+# Method to use when reloading the server
+# Valid options are 'restart' and 'graceful'
+# See http://httpd.apache.org/docs/2.2/stopping.html for information on
+# what they do and how they differ.
+#RELOAD_TYPE="graceful"
diff --git a/2.0/init/apache2.initd b/2.0/init/apache2.initd
index 92aaf81..5f72d30 100755
--- a/2.0/init/apache2.initd
+++ b/2.0/init/apache2.initd
@@ -1,38 +1,8 @@
#!/sbin/runscript
-# Copyright 1999-2005 Gentoo Foundation
+# Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-opts="${opts} reload configtest"
-
-# TODO
-# Remove all the enviroment crap, as it's not needed after baselayout 1.12.0.
-# There are still people using older versions, baselayout 1.12.0 was first
-# stable with 2006.1, so we need to wait some time before doing that.
-clear_env_except() {
-
- local save_env=$1
- shift;
-
- curr_env=$(env | sed 's/=.*//')
-
- for env_var in ${curr_env}; do
- local save=0
- for save_var in ${save_env}; do
- if [[ "${env_var}" == "${save_var}" ]]; then
- save=1
- fi
- done
-
- if [[ "${save}" == "0" ]]; then
- unset_vars="${unset_vars} -u ${env_var}"
- fi
- done
-
- env ${unset_vars} $@
-}
-
-
-
+opts="configtest fullstatus graceful gracefulstop modules reload"
depend() {
need net
@@ -47,38 +17,32 @@ configtest() {
}
checkconfig() {
-
SERVERROOT="${SERVERROOT:-/usr/lib/apache2}"
if [ ! -d ${SERVERROOT} ]; then
eerror "SERVERROOT does not exist: ${SERVERROOT}"
return 1
fi
-
+
CONFIGFILE="${CONFIGFILE:-/etc/apache2/httpd.conf}"
- [ ${CONFIGFILE:0:1} != "/" ] && CONFIGFILE="${SERVERROOT}/${CONFIGFILE}"
+ [ "${CONFIGFILE#/}" = "${CONFIGFILE}" ] && CONFIGFILE="${SERVERROOT}/${CONFIGFILE}"
if [ ! -r "${CONFIGFILE}" ]; then
eerror "Unable to read configuration file: ${CONFIGFILE}"
return 1
fi
-
APACHE2_OPTS="${APACHE2_OPTS} -d ${SERVERROOT}"
APACHE2_OPTS="${APACHE2_OPTS} -f ${CONFIGFILE}"
[ -n "${STARTUPERRORLOG}" ] && APACHE2_OPTS="${APACHE2_OPTS} -E ${STARTUPERRORLOG}"
- # set a sane default for KEEPENV
- KEEPENV=${KEEPENV:-PATH}
-
APACHE2="/usr/sbin/apache2"
-
- # TODO kill the environment crap... see note above
- clear_env_except "${KEEPENV}" ${APACHE2} ${APACHE2_OPTS} -t 1>/dev/null 2>&1
+
+ ${APACHE2} ${APACHE2_OPTS} -t 1>/dev/null 2>&1
ret=$?
if [ $ret -ne 0 ]; then
eerror "Apache2 has detected a syntax error in your configuration files:"
${APACHE2} ${APACHE2_OPTS} -t
fi
-
+
return $ret
}
@@ -86,22 +50,72 @@ start() {
checkconfig || return 1
ebegin "Starting apache2"
[ -f /var/log/apache2/ssl_scache ] && rm /var/log/apache2/ssl_scache
-
- # TODO kill the environment crap... see note above
- clear_env_except "${KEEPENV}" /sbin/start-stop-daemon --start --exec ${APACHE2} --pidfile /var/run/apache2.pid -- ${APACHE2_OPTS} -k start
+
+ start-stop-daemon --start --exec ${APACHE2} -- ${APACHE2_OPTS} -k start
eend $?
}
stop() {
checkconfig || return 1
ebegin "Stopping apache2"
- /sbin/start-stop-daemon --stop --retry -TERM/5/-TERM/5/-KILL/5 --exec ${APACHE2} --pidfile /var/run/apache2.pid
+ start-stop-daemon --stop --retry -TERM/5/-KILL/5 --exec ${APACHE2} --pidfile /var/run/apache2.pid
eend $?
}
reload() {
+ RELOAD_TYPE="${RELOAD_TYPE:-graceful}"
+
checkconfig || return 1
- ebegin "Doing a graceful restart of apache2"
- /sbin/start-stop-daemon --stop --signal USR1 --exec ${APACHE2} --pidfile /var/run/apache2.pid
+ if [ "${RELOAD_TYPE}" = "restart" ]; then
+ ebegin "Restarting apache2"
+ start-stop-daemon --stop --oknodo --signal HUP --exec ${APACHE2} --pidfile /var/run/apache2.pid
+ eend $?
+ elif [ "${RELOAD_TYPE}" = "graceful" ]; then
+ ebegin "Gracefully restarting apache2"
+ start-stop-daemon --stop --oknodo --signal USR1 --exec ${APACHE2} --pidfile /var/run/apache2.pid
+ eend $?
+ else
+ eerror "${RELOAD_TYPE} is not a valid RELOAD_TYPE. Please edit /etc/conf.d/apache2"
+ fi
+}
+
+graceful() {
+ checkconfig || return 1
+ ebegin "Gracefully restarting apache2"
+ start-stop-daemon --stop --signal USR1 --exec ${APACHE2} --pidfile /var/run/apache2.pid
+ eend $?
+}
+
+gracefulstop() {
+ checkconfig || return 1
+
+ # zap!
+ if service_started "${myservice}"; then
+ mark_service_stopped "${myservice}"
+ fi
+
+ ebegin "Gracefully stopping apache2"
+ # 28 is SIGWINCH
+ start-stop-daemon --stop --signal 28 --exec ${APACHE2} --pidfile /var/run/apache2.pid
eend $?
}
+
+modules() {
+ checkconfig || return 1
+
+ ${APACHE2} ${APACHE2_OPTS} -M 2>&1
+}
+
+status() {
+ LYNX="${LYNX:-lynx -dump}"
+ STATUSURL="${STATUSURL:-http://localhost/server-status}"
+
+ ${LYNX} ${STATUSURL} | awk ' /process$/ { print; exit } { print } '
+}
+
+fullstatus() {
+ LYNX="${LYNX:-lynx -dump}"
+ STATUSURL="${STATUSURL:-http://localhost/server-status}"
+
+ ${LYNX} ${STATUSURL}
+}
diff --git a/2.0/patches/01_all_gentoo_base.patch b/2.0/patches/01_all_gentoo_base.patch
index bf27f0b..30c17ea 100644
--- a/2.0/patches/01_all_gentoo_base.patch
+++ b/2.0/patches/01_all_gentoo_base.patch
@@ -4,8 +4,9 @@
modules/ssl/ssl_engine_mutex.c | 2 ++
server/Makefile.in | 3 +++
server/core.c | 2 +-
+ support/apachectl.in | 22 +++++++++++++++++++---
support/apxs.in | 13 -------------
- 6 files changed, 8 insertions(+), 16 deletions(-)
+ 7 files changed, 27 insertions(+), 19 deletions(-)
--- a/Makefile.in
+++ b/Makefile.in
@@ -25,7 +26,7 @@
/* The path to the suExec wrapper, can be overridden in Configuration */
#ifndef SUEXEC_BIN
-#define SUEXEC_BIN HTTPD_ROOT "/bin/suexec"
-+#define SUEXEC_BIN "/usr/sbin/suexec"
++#define SUEXEC_BIN "/usr/sbin/suexec2"
#endif
/* The timeout for waiting for messages */
@@ -63,6 +64,52 @@
}
/*
+--- a/support/apachectl.in
++++ b/support/apachectl.in
+@@ -41,17 +41,25 @@ ARGV="$@"
+ # -------------------- --------------------
+ #
+ # the path to your httpd binary, including options if necessary
+-HTTPD='@exp_sbindir@/@progname@'
++. /etc/conf.d/apache2
++if [ -n ${MPM} ] && [ -x @exp_sbindir@/@progname@.${MPM} ]; then
++ HTTPD="@exp_sbindir@/@progname@.${MPM} ${APACHE2_OPTS}"
++else
++ HTTPD="@exp_sbindir@/@progname@ ${APACHE2_OPTS}"
++fi
+ #
+ # pick up any necessary environment variables
+-if test -f @exp_sbindir@/envvars; then
+- . @exp_sbindir@/envvars
++if test -f @exp_installbuilddir@/envvars; then
++ . @exp_installbuilddir@/envvars
+ fi
+ #
+ # a command that outputs a formatted text version of the HTML at the
+ # url given on the command line. Designed for lynx, however other
+ # programs may work.
+ LYNX="lynx -dump"
++if ! type -p lynx 2>&1 >/dev/null; then
++ LYNX=no
++fi
+ #
+ # the URL to your server's mod_status status page. If you do not
+ # have one, then status and fullstatus will not work.
+@@ -75,6 +83,14 @@ if [ "x$ARGV" = "x" ] ; then
+ ARGV="-h"
+ fi
+
++if [ "${LYNX}" = "no" ] && [ "${ARGV}" = "status" -o "${ARGV}" = "fullstatus" ]; then
++ echo >&2 "lynx not found!"
++ echo >&2 ""
++ echo >&2 "You need to emerge 'www-client/lynx' for status monitoring via the"
++ echo >&2 "'status' and 'fullstatus' commands to work."
++ exit 1
++fi
++
+ case $ARGV in
+ start|stop|restart|graceful)
+ $HTTPD -k $ARGV
--- a/support/apxs.in
+++ b/support/apxs.in
@@ -199,19 +199,6 @@ if ($0 =~ m:support/apxs$:) {
diff --git a/2.0/patches/03_all_gentoo-apache-tools.patch b/2.0/patches/03_all_gentoo-apache-tools.patch
deleted file mode 100644
index e4c62e1..0000000
--- a/2.0/patches/03_all_gentoo-apache-tools.patch
+++ /dev/null
@@ -1,68 +0,0 @@
----
- Makefile.in | 10 ++++++++--
- support/Makefile.in | 16 +++-------------
- 2 files changed, 11 insertions(+), 15 deletions(-)
-
---- a/Makefile.in
-+++ b/Makefile.in
-@@ -183,14 +183,20 @@ install-include:
- @cp -p $(srcdir)/os/$(OS_DIR)/*.h $(DESTDIR)$(includedir)
- @chmod 644 $(DESTDIR)$(includedir)/*.h
-
-+MAN1=
-+MAN8=httpd.8 suexec.8 apxs.8
- install-man:
- @echo Installing man pages and online manual
- @test -d $(DESTDIR)$(mandir) || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)
- @test -d $(DESTDIR)$(mandir)/man1 || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man1
- @test -d $(DESTDIR)$(mandir)/man8 || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man8
- @test -d $(DESTDIR)$(manualdir) || $(MKINSTALLDIRS) $(DESTDIR)$(manualdir)
-- @cp -p $(top_srcdir)/docs/man/*.1 $(DESTDIR)$(mandir)/man1
-- @cp -p $(top_srcdir)/docs/man/*.8 $(DESTDIR)$(mandir)/man8
-+ @for i in $(MAN1) ; do \
-+ cp -p $(top_srcdir)/docs/man/$$i $(DESTDIR)$(mandir)/man1; \
-+ done
-+ @for i in $(MAN8) ; do \
-+ cp -p $(top_srcdir)/docs/man/$$i $(DESTDIR)$(mandir)/man8; \
-+ done
- @(cd $(top_srcdir)/docs/manual && cp -rp * $(DESTDIR)$(manualdir))
- @(cd $(DESTDIR)$(manualdir) && find . -name ".svn" -type d -print | xargs rm -rf 2>/dev/null ) || true
-
---- a/support/Makefile.in
-+++ b/support/Makefile.in
-@@ -1,9 +1,8 @@
--DISTCLEAN_TARGETS = apxs apachectl dbmmanage log_server_status \
-- logresolve.pl phf_abuse_log.cgi split-logfile envvars-std
-+DISTCLEAN_TARGETS = apxs
-
- CLEAN_TARGETS = suexec
-
--PROGRAMS = htpasswd htdigest rotatelogs logresolve ab checkgid htdbm httxt2dbm
-+PROGRAMS = apxs
- TARGETS = $(PROGRAMS)
-
- PROGRAM_LDADD = $(UTIL_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(EXTRA_LIBS) $(AP_LIBS)
-@@ -12,22 +11,13 @@ PROGRAM_DEPENDENCIES =
- include $(top_builddir)/build/rules.mk
-
- install:
-- @test -d $(DESTDIR)$(bindir) || $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
- @test -d $(DESTDIR)$(sbindir) || $(MKINSTALLDIRS) $(DESTDIR)$(sbindir)
-- @test -d $(DESTDIR)$(libexecdir) || $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir)
-- @cp -p $(top_builddir)/server/httpd.exp $(DESTDIR)$(libexecdir)
-- @for i in apxs apachectl dbmmanage; do \
-+ @for i in $(PROGRAMS) ; do \
- if test -f "$(builddir)/$$i"; then \
- cp -p $$i $(DESTDIR)$(sbindir); \
- chmod 755 $(DESTDIR)$(sbindir)/$$i; \
- fi ; \
- done
-- @if test -f "$(builddir)/envvars-std"; then \
-- cp -p envvars-std $(DESTDIR)$(sbindir); \
-- if test ! -f $(DESTDIR)$(sbindir)/envvars; then \
-- cp -p envvars-std $(DESTDIR)$(sbindir)/envvars ; \
-- fi ; \
-- fi
-
- htpasswd_OBJECTS = htpasswd.lo
- htpasswd: $(htpasswd_OBJECTS)
diff --git a/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch b/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch
deleted file mode 100644
index 8833481..0000000
--- a/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch
+++ /dev/null
@@ -1,332 +0,0 @@
----
- modules/ssl/mod_ssl.h | 4
- modules/ssl/ssl_engine_io.c | 185 ++++++++++++++++++++++++++++++++++++++++
- modules/ssl/ssl_engine_kernel.c | 96 ++++++--------------
- 3 files changed, 218 insertions(+), 67 deletions(-)
-
---- a/modules/ssl/mod_ssl.h
-+++ b/modules/ssl/mod_ssl.h
-@@ -682,6 +682,10 @@ void ssl_io_filter_init(conn_rec
- void ssl_io_filter_register(apr_pool_t *);
- long ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
-
-+/* ssl_io_buffer_fill fills the setaside buffering of the HTTP request
-+ * to allow an SSL renegotiation to take place. */
-+int ssl_io_buffer_fill(request_rec *r);
-+
- /* PRNG */
- int ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);
-
---- a/modules/ssl/ssl_engine_io.c
-+++ b/modules/ssl/ssl_engine_io.c
-@@ -880,6 +880,7 @@ static apr_status_t ssl_io_filter_error(
- }
-
- static const char ssl_io_filter[] = "SSL/TLS Filter";
-+static const char ssl_io_buffer[] = "SSL/TLS Buffer";
-
- /*
- * Close the SSL part of the socket connection
-@@ -1373,6 +1374,187 @@ static apr_status_t ssl_io_filter_output
- return status;
- }
-
-+/* 128K maximum buffer size by default. */
-+#ifndef SSL_MAX_IO_BUFFER
-+#define SSL_MAX_IO_BUFFER (128 * 1024)
-+#endif
-+
-+struct modssl_buffer_ctx {
-+ apr_bucket_brigade *bb;
-+ apr_pool_t *pool;
-+};
-+
-+int ssl_io_buffer_fill(request_rec *r)
-+{
-+ conn_rec *c = r->connection;
-+ struct modssl_buffer_ctx *ctx;
-+ apr_bucket_brigade *tempb;
-+ apr_off_t total = 0; /* total length buffered */
-+ int eos = 0; /* non-zero once EOS is seen */
-+
-+ /* Create the context which will be passed to the input filter;
-+ * containing a setaside pool and a brigade which constrain the
-+ * lifetime of the buffered data. */
-+ ctx = apr_palloc(r->pool, sizeof *ctx);
-+ apr_pool_create(&ctx->pool, r->pool);
-+ ctx->bb = apr_brigade_create(ctx->pool, c->bucket_alloc);
-+
-+ /* ... and a temporary brigade. */
-+ tempb = apr_brigade_create(r->pool, c->bucket_alloc);
-+
-+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "filling buffer");
-+
-+ do {
-+ apr_status_t rv;
-+ apr_bucket *e, *next;
-+
-+ /* The request body is read from the protocol-level input
-+ * filters; the buffering filter will reinject it from that
-+ * level, allowing content/resource filters to run later, if
-+ * necessary. */
-+
-+ rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES,
-+ APR_BLOCK_READ, 8192);
-+ if (rv) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-+ "could not read request body for SSL buffer");
-+ return HTTP_INTERNAL_SERVER_ERROR;
-+ }
-+
-+ /* Iterate through the returned brigade: setaside each bucket
-+ * into the context's pool and move it into the brigade. */
-+ for (e = APR_BRIGADE_FIRST(tempb);
-+ e != APR_BRIGADE_SENTINEL(tempb) && !eos; e = next) {
-+ const char *data;
-+ apr_size_t len;
-+
-+ next = APR_BUCKET_NEXT(e);
-+
-+ if (APR_BUCKET_IS_EOS(e)) {
-+ eos = 1;
-+ } else if (!APR_BUCKET_IS_METADATA(e)) {
-+ rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
-+ if (rv != APR_SUCCESS) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-+ "could not read bucket for SSL buffer");
-+ return HTTP_INTERNAL_SERVER_ERROR;
-+ }
-+ total += len;
-+ }
-+
-+ rv = apr_bucket_setaside(e, ctx->pool);
-+ if (rv != APR_SUCCESS) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-+ "could not setaside bucket for SSL buffer");
-+ return HTTP_INTERNAL_SERVER_ERROR;
-+ }
-+
-+ APR_BUCKET_REMOVE(e);
-+ APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
-+ }
-+
-+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-+ "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d",
-+ total, eos);
-+
-+ /* Fail if this exceeds the maximum buffer size. */
-+ if (total > SSL_MAX_IO_BUFFER) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-+ "request body exceeds maximum size for SSL buffer");
-+ return HTTP_REQUEST_ENTITY_TOO_LARGE;
-+ }
-+
-+ } while (!eos);
-+
-+ apr_brigade_destroy(tempb);
-+
-+ /* Insert the filter which will supply the buffered data. */
-+ ap_add_input_filter(ssl_io_buffer, ctx, r, c);
-+
-+ return 0;
-+}
-+
-+/* This input filter supplies the buffered request body to the caller
-+ * from the brigade stored in f->ctx. */
-+static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
-+ apr_bucket_brigade *bb,
-+ ap_input_mode_t mode,
-+ apr_read_type_e block,
-+ apr_off_t bytes)
-+{
-+ struct modssl_buffer_ctx *ctx = f->ctx;
-+ apr_status_t rv;
-+
-+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,
-+ "read from buffered SSL brigade, mode %d, "
-+ "%" APR_OFF_T_FMT " bytes",
-+ mode, bytes);
-+
-+ if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
-+ return APR_ENOTIMPL;
-+ }
-+
-+ if (mode == AP_MODE_READBYTES) {
-+ apr_bucket *e;
-+
-+ /* Partition the buffered brigade. */
-+ rv = apr_brigade_partition(ctx->bb, bytes, &e);
-+ if (rv && rv != APR_INCOMPLETE) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
-+ "could not partition buffered SSL brigade");
-+ ap_remove_input_filter(f);
-+ return rv;
-+ }
-+
-+ /* If the buffered brigade contains less then the requested
-+ * length, just pass it all back. */
-+ if (rv == APR_INCOMPLETE) {
-+ APR_BRIGADE_CONCAT(bb, ctx->bb);
-+ } else {
-+ apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb);
-+
-+ e = APR_BUCKET_PREV(e);
-+
-+ /* Unsplice the partitioned segment and move it into the
-+ * passed-in brigade; no convenient way to do this with
-+ * the APR_BRIGADE_* macros. */
-+ APR_RING_UNSPLICE(d, e, link);
-+ APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link);
-+
-+ APR_BRIGADE_CHECK_CONSISTENCY(bb);
-+ APR_BRIGADE_CHECK_CONSISTENCY(ctx->bb);
-+ }
-+ }
-+ else {
-+ /* Split a line into the passed-in brigade. */
-+ rv = apr_brigade_split_line(bb, ctx->bb, mode, bytes);
-+
-+ if (rv) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
-+ "could not split line from buffered SSL brigade");
-+ ap_remove_input_filter(f);
-+ return rv;
-+ }
-+ }
-+
-+ if (APR_BRIGADE_EMPTY(ctx->bb)) {
-+ apr_bucket *e = APR_BRIGADE_LAST(bb);
-+
-+ /* Ensure that the brigade is terminated by an EOS if the
-+ * buffered request body has been entirely consumed. */
-+ if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) {
-+ e = apr_bucket_eos_create(f->c->bucket_alloc);
-+ APR_BRIGADE_INSERT_TAIL(bb, e);
-+ }
-+
-+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,
-+ "buffered SSL brigade now exhausted; removing filter");
-+ ap_remove_input_filter(f);
-+ }
-+
-+ return APR_SUCCESS;
-+}
-+
- static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,
- SSL *ssl)
- {
-@@ -1430,6 +1612,9 @@ void ssl_io_filter_register(apr_pool_t *
- {
- ap_register_input_filter (ssl_io_filter, ssl_io_filter_input, NULL, AP_FTYPE_CONNECTION + 5);
- ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);
-+
-+ ap_register_input_filter (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL - 1);
-+
- return;
- }
-
---- a/modules/ssl/ssl_engine_kernel.c
-+++ b/modules/ssl/ssl_engine_kernel.c
-@@ -483,73 +483,35 @@ int ssl_hook_Access(request_rec *r)
- }
- #endif /* HAVE_SSL_SET_CERT_STORE */
-
-- /*
-- * SSL renegotiations in conjunction with HTTP
-- * requests using the POST method are not supported.
-- *
-- * Background:
-- *
-- * 1. When the client sends a HTTP/HTTPS request, Apache's core code
-- * reads only the request line ("METHOD /path HTTP/x.y") and the
-- * attached MIME headers ("Foo: bar") up to the terminating line ("CR
-- * LF"). An attached request body (for instance the data of a POST
-- * method) is _NOT_ read. Instead it is read by mod_cgi's content
-- * handler and directly passed to the CGI script.
-- *
-- * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
-- * This is implemented by performing an SSL renegotiation of the
-- * re-configured parameters after the request is read, but before the
-- * response is sent. In more detail: the renegotiation happens after the
-- * request line and MIME headers were read, but _before_ the attached
-- * request body is read. The reason simply is that in the HTTP protocol
-- * usually there is no acknowledgment step between the headers and the
-- * body (there is the 100-continue feature and the chunking facility
-- * only), so Apache has no API hook for this step.
-- *
-- * 3. the problem now occurs when the client sends a POST request for
-- * URL /foo via HTTPS the server and the server has SSL parameters
-- * re-configured on a per-URL basis for /foo. Then mod_ssl has to
-- * perform an SSL renegotiation after the request was read and before
-- * the response is sent. But the problem is the pending POST body data
-- * in the receive buffer of SSL (which Apache still has not read - it's
-- * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
-- * the renegotiation the pending data leads to an I/O error.
-- *
-- * Solution Idea:
-- *
-- * There are only two solutions: Either to simply state that POST
-- * requests to URLs with SSL re-configurations are not allowed, or to
-- * renegotiate really after the _complete_ request (i.e. including
-- * the POST body) was read. Obviously the latter would be preferred,
-- * but it cannot be done easily inside Apache, because as already
-- * mentioned, there is no API step between the body reading and the body
-- * processing. And even when we mod_ssl would hook directly into the
-- * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
-- * course. So the only general solution is to suck in the pending data
-- * of the request body from the OpenSSL BIO into the Apache BUFF. Then
-- * the renegotiation can be done and after this step Apache can proceed
-- * processing the request as before.
-- *
-- * Solution Implementation:
-- *
-- * We cannot simply suck in the data via an SSL_read-based loop because of
-- * HTTP chunking. Instead we _have_ to use the Apache API for this step which
-- * is aware of HTTP chunking. So the trick is to suck in the pending request
-- * data via the Apache API (which uses Apache's BUFF code and in the
-- * background mod_ssl's I/O glue code) and re-inject it later into the Apache
-- * BUFF code again. This way the data flows twice through the Apache BUFF, of
-- * course. But this way the solution doesn't depend on any Apache specifics
-- * and is fully transparent to Apache modules.
-- *
-- * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !!
-- */
-- if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) {
-- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
-- "SSL Re-negotiation in conjunction "
-- "with POST method not supported! "
-- "hint: try SSLOptions +OptRenegotiate");
--
-- return HTTP_METHOD_NOT_ALLOWED;
-+ /* If a renegotiation is now required for this location, and the
-+ * request includes a message body (and the client has not
-+ * requested a "100 Continue" response), then the client will be
-+ * streaming the request body over the wire already. In that
-+ * case, it is not possible to stop and perform a new SSL
-+ * handshake immediately; once the SSL library moves to the
-+ * "accept" state, it will reject the SSL packets which the client
-+ * is sending for the request body.
-+ *
-+ * To allow authentication to complete in this auth hook, the
-+ * solution used here is to fill a (bounded) buffer with the
-+ * request body, and then to reinject that request body later.
-+ */
-+ if (renegotiate && !renegotiate_quick
-+ && (apr_table_get(r->headers_in, "transfer-encoding")
-+ || (apr_table_get(r->headers_in, "content-length")
-+ && strcmp(apr_table_get(r->headers_in, "content-length"), "0")))
-+ && !r->expecting_100) {
-+ int rv;
-+
-+ /* Fill the I/O buffer with the request body if possible. */
-+ rv = ssl_io_buffer_fill(r);
-+
-+ if (rv) {
-+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-+ "could not buffer message body to allow "
-+ "SSL renegotiation to proceed");
-+ return rv;
-+ }
- }
-
- /*
diff --git a/2.0/patches/80_all_CVE-2007-5752.patch b/2.0/patches/80_all_CVE-2007-5752.patch
deleted file mode 100644
index cc2c057..0000000
--- a/2.0/patches/80_all_CVE-2007-5752.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-Index: modules/generators/mod_status.c
-===================================================================
---- modules/generators/mod_status.c (revision 555481)
-+++ modules/generators/mod_status.c (revision 555482)
-@@ -269,7 +269,7 @@
- if (r->method_number != M_GET)
- return DECLINED;
-
-- ap_set_content_type(r, "text/html");
-+ ap_set_content_type(r, "text/html; charset=ISO-8859-1");
-
- /*
- * Simple table-driven form data set parser that lets you alter the header
-@@ -298,7 +298,7 @@
- no_table_report = 1;
- break;
- case STAT_OPT_AUTO:
-- ap_set_content_type(r, "text/plain");
-+ ap_set_content_type(r, "text/plain; charset=ISO-8859-1");
- short_report = 1;
- break;
- }
-@@ -664,7 +664,8 @@
- ap_escape_html(r->pool,
- ws_record->client),
- ap_escape_html(r->pool,
-- ws_record->request),
-+ ap_escape_logitem(r->pool,
-+ ws_record->request)),
- ap_escape_html(r->pool,
- ws_record->vhost));
- }
-@@ -753,7 +754,8 @@
- ap_escape_html(r->pool,
- ws_record->vhost),
- ap_escape_html(r->pool,
-- ws_record->request));
-+ ap_escape_logitem(r->pool,
-+ ws_record->request)));
- } /* no_table_report */
- } /* for (j...) */
- } /* for (i...) */
diff --git a/2.0/patches/81_all_CVE-2007-3304.patch b/2.0/patches/81_all_CVE-2007-3304.patch
deleted file mode 100644
index 7e70654..0000000
--- a/2.0/patches/81_all_CVE-2007-3304.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-Index: server/mpm_common.c
-===================================================================
---- server/mpm_common.c (revision 556297)
-+++ server/mpm_common.c (revision 556298)
-@@ -110,6 +110,11 @@
- apr_proc_t proc;
- apr_status_t waitret;
-
-+ /* Ensure pid sanity. */
-+ if (pid < 1) {
-+ return 1;
-+ }
-+
- proc.pid = pid;
- waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT);
- if (waitret != APR_CHILD_NOTDONE) {
diff --git a/2.0/patches/82_all_CVE-2007-1863.patch b/2.0/patches/82_all_CVE-2007-1863.patch
deleted file mode 100644
index af5b458..0000000
--- a/2.0/patches/82_all_CVE-2007-1863.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-Index: modules/experimental/cache_util.c
-===================================================================
---- modules/experimental/cache_util.c (revision 556618)
-+++ modules/experimental/cache_util.c (revision 556619)
-@@ -186,7 +186,8 @@
- age = ap_cache_current_age(info, age_c, r->request_time);
-
- /* extract s-maxage */
-- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)) {
-+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)
-+ && val != NULL) {
- smaxage = apr_atoi64(val);
- }
- else if (cc_ceresp && ap_cache_liststr(r->pool, cc_ceresp, "s-maxage", &val)) {
-@@ -197,7 +198,8 @@
- }
-
- /* extract max-age from request */
-- if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)) {
-+ if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)
-+ && val != NULL) {
- maxage_req = apr_atoi64(val);
- }
- else {
-@@ -205,7 +207,8 @@
- }
-
- /* extract max-age from response */
-- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)) {
-+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)
-+ && val != NULL) {
- maxage_cresp = apr_atoi64(val);
- }
- else if (cc_ceresp && ap_cache_liststr(r->pool, cc_ceresp, "max-age", &val)) {
-@@ -231,14 +234,28 @@
-
- /* extract max-stale */
- if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-stale", &val)) {
-- maxstale = apr_atoi64(val);
-+ if(val != NULL) {
-+ maxstale = apr_atoi64(val);
-+ }
-+ else {
-+ /*
-+ * If no value is assigned to max-stale, then the client is willing
-+ * to accept a stale response of any age (RFC2616 14.9.3). We will
-+ * set it to one year in this case as this situation is somewhat
-+ * similar to a "never expires" Expires header (RFC2616 14.21)
-+ * which is set to a date one year from the time the response is
-+ * sent in this case.
-+ */
-+ maxstale = APR_INT64_C(86400*365);
-+ }
- }
- else {
- maxstale = 0;
- }
-
- /* extract min-fresh */
-- if (cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)) {
-+ if (cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)
-+ && val != NULL) {
- minfresh = apr_atoi64(val);
- }
- else {
-@@ -384,6 +401,9 @@
- next - val_start);
- }
- }
-+ else {
-+ *val = NULL;
-+ }
- }
- return 1;
- }
diff --git a/2.0/patches/83_all_CVE-2007-2874.patch b/2.0/patches/83_all_CVE-2007-2874.patch
deleted file mode 100644
index 0c63c1f..0000000
--- a/2.0/patches/83_all_CVE-2007-2874.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-Index: modules/proxy/proxy_util.c
-===================================================================
---- modules/proxy/proxy_util.c (revision 563328)
-+++ modules/proxy/proxy_util.c (revision 563329)
-@@ -259,70 +259,28 @@
- return NULL;
- }
-
--static const char * const lwday[7] =
--{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
--
- /*
- * If the date is a valid RFC 850 date or asctime() date, then it
-- * is converted to the RFC 1123 format, otherwise it is not modified.
-- * This routine is not very fast at doing conversions, as it uses
-- * sscanf and sprintf. However, if the date is already correctly
-- * formatted, then it exits very quickly.
-+ * is converted to the RFC 1123 format.
- */
- PROXY_DECLARE(const char *)
-- ap_proxy_date_canon(apr_pool_t *p, const char *x1)
-+ ap_proxy_date_canon(apr_pool_t *p, const char *date)
- {
-- char *x = apr_pstrdup(p, x1);
-- int wk, mday, year, hour, min, sec, mon;
-- char *q, month[4], zone[4], week[4];
-+ apr_status_t rv;
-+ char* ndate;
-
-- q = strchr(x, ',');
-- /* check for RFC 850 date */
-- if (q != NULL && q - x > 3 && q[1] == ' ') {
-- *q = '\0';
-- for (wk = 0; wk < 7; wk++)
-- if (strcmp(x, lwday[wk]) == 0)
-- break;
-- *q = ',';
-- if (wk == 7)
-- return x; /* not a valid date */
-- if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
-- q[17] != ':' || strcmp(&q[20], " GMT") != 0)
-- return x;
-- if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
-- &hour, &min, &sec, zone) != 7)
-- return x;
-- if (year < 70)
-- year += 2000;
-- else
-- year += 1900;
-+ apr_time_t time = apr_date_parse_http(date);
-+ if (!time) {
-+ return date;
- }
-- else {
--/* check for acstime() date */
-- if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
-- x[16] != ':' || x[19] != ' ' || x[24] != '\0')
-- return x;
-- if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
-- &min, &sec, &year) != 7)
-- return x;
-- for (wk = 0; wk < 7; wk++)
-- if (strcmp(week, apr_day_snames[wk]) == 0)
-- break;
-- if (wk == 7)
-- return x;
-+
-+ ndate = apr_palloc(p, APR_RFC822_DATE_LEN);
-+ rv = apr_rfc822_date(ndate, time);
-+ if (rv != APR_SUCCESS) {
-+ return date;
- }
-
--/* check date */
-- for (mon = 0; mon < 12; mon++)
-- if (strcmp(month, apr_month_snames[mon]) == 0)
-- break;
-- if (mon == 12)
-- return x;
--
-- q = apr_palloc(p, 30);
-- apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", apr_day_snames[wk],
-- mday, apr_month_snames[mon], year, hour, min, sec);
-- return q;
-+ return ndate;
- }
-
- PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
diff --git a/2.2/conf/apache2-builtin-mods b/2.2/conf/apache2-builtin-mods
index ca90c6a..a0174bd 100644
--- a/2.2/conf/apache2-builtin-mods
+++ b/2.2/conf/apache2-builtin-mods
@@ -42,8 +42,8 @@ mod_authz_user shared
mod_autoindex shared
mod_cache shared
mod_cern_meta disabled
-mod_cgi shared
-mod_cgid shared
+#mod_cgi disabled # enable via USE-flag
+#mod_cgid disabled # enable via USE-flag
mod_charset_lite disabled
mod_dav shared
mod_dav_fs shared
diff --git a/2.2/patches/04_all_mod_dbd_r553563.patch b/2.2/patches/04_all_mod_dbd_r553563.patch
deleted file mode 100644
index 51dd29b..0000000
--- a/2.2/patches/04_all_mod_dbd_r553563.patch
+++ /dev/null
@@ -1,1279 +0,0 @@
-diff -NurpP httpd-2.2.4.orig/modules/database/mod_dbd.c httpd-2.2.4/modules/database/mod_dbd.c
---- httpd-2.2.4.orig/modules/database/mod_dbd.c 2006-12-12 15:17:17.000000000 +0100
-+++ httpd-2.2.4/modules/database/mod_dbd.c 2007-08-19 15:47:47.822568162 +0200
-@@ -20,15 +20,21 @@
- * http://apache.webthing.com/database/
- */
-
--#include <ctype.h>
-+#include "apr_reslist.h"
-+#include "apr_strings.h"
-+#include "apr_hash.h"
-+#include "apr_tables.h"
-+#include "apr_lib.h"
-+#include "apr_dbd.h"
-+
-+#define APR_WANT_MEMFUNC
-+#define APR_WANT_STRFUNC
-+#include "apr_want.h"
-
- #include "http_protocol.h"
- #include "http_config.h"
- #include "http_log.h"
- #include "http_request.h"
--#include "apr_reslist.h"
--#include "apr_strings.h"
--#include "apr_dbd.h"
- #include "mod_dbd.h"
-
- extern module AP_MODULE_DECLARE_DATA dbd_module;
-@@ -40,126 +46,199 @@ extern module AP_MODULE_DECLARE_DATA dbd
- #define NMAX_SET 0x4
- #define EXPTIME_SET 0x8
-
--typedef struct dbd_prepared {
-- const char *label;
-- const char *query;
-- struct dbd_prepared *next;
--} dbd_prepared;
--typedef struct svr_cfg {
-+typedef struct {
-+ server_rec *server;
- const char *name;
- const char *params;
- int persist;
-- dbd_prepared *prepared;
- #if APR_HAS_THREADS
-- apr_thread_mutex_t *mutex;
-- apr_pool_t *pool;
-- apr_reslist_t *dbpool;
- int nmin;
- int nkeep;
- int nmax;
- int exptime;
-+ int set;
-+#endif
-+ apr_hash_t *queries;
-+} dbd_cfg_t;
-+
-+typedef struct dbd_group_t dbd_group_t;
-+
-+struct dbd_group_t {
-+ dbd_cfg_t *cfg;
-+ dbd_group_t *next;
-+ apr_pool_t *pool;
-+#if APR_HAS_THREADS
-+ apr_thread_mutex_t *mutex;
-+ apr_reslist_t *reslist;
-+ int destroyed;
- #else
-- ap_dbd_t *conn;
-+ ap_dbd_t *rec;
- #endif
-- unsigned int set;
-+};
-+
-+typedef struct {
-+ dbd_cfg_t *cfg;
-+ dbd_group_t *group;
- } svr_cfg;
-
- typedef enum { cmd_name, cmd_params, cmd_persist,
- cmd_min, cmd_keep, cmd_max, cmd_exp
- } cmd_parts;
-
--static apr_hash_t *dbd_prepared_defns;
-+static apr_pool_t *config_pool;
-+static dbd_group_t *group_list;
-
- /* a default DBDriver value that'll generate meaningful error messages */
- static const char *const no_dbdriver = "[DBDriver unset]";
-
--#define ISINT(val) \
-- for (p = val; *p; ++p) \
-- if (!isdigit(*p)) \
-- return "Argument must be numeric!"
--static const char *dbd_param(cmd_parms *cmd, void *cfg, const char *val)
-+/* A default nmin of >0 will help with generating meaningful
-+ * startup error messages if the database is down.
-+ */
-+#define DEFAULT_NMIN 1
-+#define DEFAULT_NKEEP 2
-+#define DEFAULT_NMAX 10
-+#define DEFAULT_EXPTIME 300
-+
-+static void *create_dbd_config(apr_pool_t *pool, server_rec *s)
-+{
-+ svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
-+ dbd_cfg_t *cfg = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
-+
-+ cfg->server = s;
-+ cfg->name = no_dbdriver; /* to generate meaningful error messages */
-+ cfg->params = ""; /* don't risk segfault on misconfiguration */
-+ cfg->persist = -1;
-+#if APR_HAS_THREADS
-+ cfg->nmin = DEFAULT_NMIN;
-+ cfg->nkeep = DEFAULT_NKEEP;
-+ cfg->nmax = DEFAULT_NMAX;
-+ cfg->exptime = DEFAULT_EXPTIME;
-+#endif
-+ cfg->queries = apr_hash_make(pool);
-+
-+ return svr;
-+}
-+
-+static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv)
-+{
-+ dbd_cfg_t *base = ((svr_cfg*) basev)->cfg;
-+ dbd_cfg_t *add = ((svr_cfg*) addv)->cfg;
-+ svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg));
-+ dbd_cfg_t *new = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t));
-+
-+ new->server = add->server;
-+ new->name = (add->name != no_dbdriver) ? add->name : base->name;
-+ new->params = strcmp(add->params, "") ? add->params : base->params;
-+ new->persist = (add->persist != -1) ? add->persist : base->persist;
-+#if APR_HAS_THREADS
-+ new->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;
-+ new->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;
-+ new->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;
-+ new->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;
-+#endif
-+ new->queries = apr_hash_overlay(pool, add->queries, base->queries);
-+
-+ return svr;
-+}
-+
-+#define ISINT(val) do { \
-+ const char *p; \
-+ \
-+ for (p = val; *p; ++p) { \
-+ if (!apr_isdigit(*p)) { \
-+ return "Argument must be numeric!"; \
-+ } \
-+ } \
-+ } while (0)
-+
-+static const char *dbd_param(cmd_parms *cmd, void *dconf, const char *val)
- {
-- const char *p;
- const apr_dbd_driver_t *driver = NULL;
-- svr_cfg *svr = (svr_cfg*) ap_get_module_config
-- (cmd->server->module_config, &dbd_module);
-+ svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
-+ &dbd_module);
-+ dbd_cfg_t *cfg = svr->cfg;
-
- switch ((long) cmd->info) {
- case cmd_name:
-- svr->name = val;
-+ cfg->name = val;
- /* loading the driver involves once-only dlloading that is
- * best done at server startup. This also guarantees that
- * we won't return an error later.
- */
-- switch (apr_dbd_get_driver(cmd->pool, svr->name, &driver)) {
-+ switch (apr_dbd_get_driver(cmd->pool, cfg->name, &driver)) {
- case APR_ENOTIMPL:
-- return apr_psprintf(cmd->pool, "DBD: No driver for %s", svr->name);
-+ return apr_psprintf(cmd->pool, "DBD: No driver for %s", cfg->name);
- case APR_EDSOOPEN:
- return apr_psprintf(cmd->pool,
-+#ifdef NETWARE
-+ "DBD: Can't load driver file dbd%s.nlm",
-+#else
- "DBD: Can't load driver file apr_dbd_%s.so",
-- svr->name);
-+#endif
-+ cfg->name);
- case APR_ESYMNOTFOUND:
- return apr_psprintf(cmd->pool,
- "DBD: Failed to load driver apr_dbd_%s_driver",
-- svr->name);
-+ cfg->name);
- }
- break;
- case cmd_params:
-- svr->params = val;
-+ cfg->params = val;
- break;
- #if APR_HAS_THREADS
- case cmd_min:
- ISINT(val);
-- svr->nmin = atoi(val);
-- svr->set |= NMIN_SET;
-+ cfg->nmin = atoi(val);
-+ cfg->set |= NMIN_SET;
- break;
- case cmd_keep:
- ISINT(val);
-- svr->nkeep = atoi(val);
-- svr->set |= NKEEP_SET;
-+ cfg->nkeep = atoi(val);
-+ cfg->set |= NKEEP_SET;
- break;
- case cmd_max:
- ISINT(val);
-- svr->nmax = atoi(val);
-- svr->set |= NMAX_SET;
-+ cfg->nmax = atoi(val);
-+ cfg->set |= NMAX_SET;
- break;
- case cmd_exp:
- ISINT(val);
-- svr->exptime = atoi(val);
-- svr->set |= EXPTIME_SET;
-+ cfg->exptime = atoi(val);
-+ cfg->set |= EXPTIME_SET;
- break;
- #endif
- }
-+
- return NULL;
- }
--static const char *dbd_param_flag(cmd_parms *cmd, void *cfg, int flag)
-+
-+static const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag)
- {
-- svr_cfg *svr = (svr_cfg*) ap_get_module_config
-- (cmd->server->module_config, &dbd_module);
-+ svr_cfg *svr = ap_get_module_config(cmd->server->module_config,
-+ &dbd_module);
-
- switch ((long) cmd->info) {
- case cmd_persist:
-- svr->persist = flag;
-+ svr->cfg->persist = flag;
- break;
- }
-+
- return NULL;
- }
--DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,
-- const char *label)
--{
-- dbd_prepared *prepared = apr_pcalloc(s->process->pool, sizeof(dbd_prepared));
-- const char *key = apr_psprintf(s->process->pool, "%pp", s);
-- prepared->label = label;
-- prepared->query = query;
-- prepared->next = apr_hash_get(dbd_prepared_defns, key, APR_HASH_KEY_STRING);
-- apr_hash_set(dbd_prepared_defns, key, APR_HASH_KEY_STRING, prepared);
--}
--static const char *dbd_prepare(cmd_parms *cmd, void *cfg, const char *query,
-+
-+static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query,
- const char *label)
- {
-+ if (!label) {
-+ label = query;
-+ query = "";
-+ }
-+
- ap_dbd_prepare(cmd->server, query, label);
-+
- return NULL;
- }
-+
- static const command_rec dbd_cmds[] = {
- AP_INIT_TAKE1("DBDriver", dbd_param, (void*)cmd_name, RSRC_CONF,
- "SQL Driver"),
-@@ -167,8 +246,9 @@ static const command_rec dbd_cmds[] = {
- "SQL Driver Params"),
- AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF,
- "Use persistent connection/pool"),
-- AP_INIT_TAKE2("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,
-- "Prepared SQL statement, label"),
-+ AP_INIT_TAKE12("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF,
-+ "SQL statement to prepare (or nothing, to override "
-+ "statement inherited from main server) and label"),
- #if APR_HAS_THREADS
- AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF,
- "Minimum number of connections"),
-@@ -183,370 +263,545 @@ static const command_rec dbd_cmds[] = {
- #endif
- {NULL}
- };
--static void *dbd_merge(apr_pool_t *pool, void *BASE, void *ADD) {
-- svr_cfg *base = (svr_cfg*) BASE;
-- svr_cfg *add = (svr_cfg*) ADD;
-- svr_cfg *cfg = apr_pcalloc(pool, sizeof(svr_cfg));
-- cfg->name = (add->name != no_dbdriver) ? add->name : base->name;
-- cfg->params = strcmp(add->params, "") ? add->params : base->params;
-- cfg->persist = (add->persist == -1) ? base->persist : add->persist;
--#if APR_HAS_THREADS
-- cfg->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin;
-- cfg->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep;
-- cfg->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax;
-- cfg->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime;
--#endif
-- cfg->set = add->set | base->set;
-- cfg->prepared = (add->prepared != NULL) ? add->prepared : base->prepared;
-- return (void*) cfg;
-+
-+static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
-+ apr_pool_t *ptemp)
-+{
-+ config_pool = pconf;
-+ group_list = NULL;
-+ return OK;
- }
--/* A default nmin of >0 will help with generating meaningful
-- * startup error messages if the database is down.
-- */
--#define DEFAULT_NMIN 1
--#define DEFAULT_NKEEP 2
--#define DEFAULT_NMAX 10
--#define DEFAULT_EXPTIME 300
--static void *dbd_cfg(apr_pool_t *p, server_rec *x)
-+
-+DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query,
-+ const char *label)
-+{
-+ svr_cfg *svr;
-+
-+ svr = ap_get_module_config(s->module_config, &dbd_module);
-+ if (!svr) {
-+ /* some modules may call from within config directive handlers, and
-+ * if these are called in a server context that contains no mod_dbd
-+ * config directives, then we have to create our own server config
-+ */
-+ svr = create_dbd_config(config_pool, s);
-+ ap_set_module_config(s->module_config, &dbd_module, svr);
-+ }
-+
-+ if (apr_hash_get(svr->cfg->queries, label, APR_HASH_KEY_STRING)
-+ && strcmp(query, "")) {
-+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
-+ "conflicting SQL statements with label %s", label);
-+ }
-+
-+ apr_hash_set(svr->cfg->queries, label, APR_HASH_KEY_STRING, query);
-+}
-+
-+typedef struct {
-+ const char *label, *query;
-+} dbd_query_t;
-+
-+static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
-+ apr_pool_t *ptemp, server_rec *s)
- {
-- svr_cfg *svr = (svr_cfg*) apr_pcalloc(p, sizeof(svr_cfg));
-- svr->params = ""; /* don't risk segfault on misconfiguration */
-- svr->name = no_dbdriver; /* to generate meaningful error messages */
-- svr->persist = -1;
--#if APR_HAS_THREADS
-- svr->nmin = DEFAULT_NMIN;
-- svr->nkeep = DEFAULT_NKEEP;
-- svr->nmax = DEFAULT_NMAX;
-- svr->exptime = DEFAULT_EXPTIME;
-+ server_rec *sp;
-+ apr_array_header_t *add_queries = apr_array_make(ptemp, 10,
-+ sizeof(dbd_query_t));
-+
-+ for (sp = s; sp; sp = sp->next) {
-+ svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module);
-+ dbd_cfg_t *cfg = svr->cfg;
-+ apr_hash_index_t *hi_first = apr_hash_first(ptemp, cfg->queries);
-+ dbd_group_t *group;
-+
-+ /* dbd_setup in 2.2.3 and under was causing spurious error messages
-+ * when dbd isn't configured. We can stop that with a quick check here
-+ * together with a similar check in ap_dbd_open (where being
-+ * unconfigured is a genuine error that must be reported).
-+ */
-+ if (cfg->name == no_dbdriver || !cfg->persist) {
-+ continue;
-+ }
-+
-+ for (group = group_list; group; group = group->next) {
-+ dbd_cfg_t *group_cfg = group->cfg;
-+ apr_hash_index_t *hi;
-+ int group_ok = 1;
-+
-+ if (strcmp(cfg->name, group_cfg->name)
-+ || strcmp(cfg->params, group_cfg->params)) {
-+ continue;
-+ }
-+
-+#if APR_HAS_THREADS
-+ if (cfg->nmin != group_cfg->nmin
-+ || cfg->nkeep != group_cfg->nkeep
-+ || cfg->nmax != group_cfg->nmax
-+ || cfg->exptime != group_cfg->exptime) {
-+ continue;
-+ }
- #endif
-- return svr;
-+
-+ add_queries->nelts = 0;
-+
-+ for (hi = hi_first; hi; hi = apr_hash_next(hi)) {
-+ const char *label, *query;
-+ const char *group_query;
-+
-+ apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
-+
-+ group_query = apr_hash_get(group_cfg->queries, label,
-+ APR_HASH_KEY_STRING);
-+
-+ if (!group_query) {
-+ dbd_query_t *add_query = apr_array_push(add_queries);
-+
-+ add_query->label = label;
-+ add_query->query = query;
-+ }
-+ else if (strcmp(query, group_query)) {
-+ group_ok = 0;
-+ break;
-+ }
-+ }
-+
-+ if (group_ok) {
-+ int i;
-+
-+ for (i = 0; i < add_queries->nelts; ++i) {
-+ dbd_query_t *add_query = ((dbd_query_t*) add_queries->elts)
-+ + i;
-+
-+ apr_hash_set(group_cfg->queries, add_query->label,
-+ APR_HASH_KEY_STRING, add_query->query);
-+ }
-+
-+ svr->group = group;
-+ break;
-+ }
-+ }
-+
-+ if (!svr->group) {
-+ svr->group = group = apr_pcalloc(pconf, sizeof(dbd_group_t));
-+
-+ group->cfg = cfg;
-+
-+ group->next = group_list;
-+ group_list = group;
-+ }
-+ }
-+
-+ return OK;
- }
--static apr_status_t dbd_prepared_init(apr_pool_t *pool, svr_cfg *svr,
-- ap_dbd_t *dbd)
-+
-+static apr_status_t dbd_prepared_init(apr_pool_t *pool, dbd_cfg_t *cfg,
-+ ap_dbd_t *rec)
- {
-- dbd_prepared *p;
-- apr_status_t ret = APR_SUCCESS;
-- apr_dbd_prepared_t *stmt;
-- dbd->prepared = apr_hash_make(pool);
-+ apr_hash_index_t *hi;
-+ apr_status_t rv = APR_SUCCESS;
-+
-+ rec->prepared = apr_hash_make(pool);
-+
-+ for (hi = apr_hash_first(pool, cfg->queries); hi;
-+ hi = apr_hash_next(hi)) {
-+ const char *label, *query;
-+ apr_dbd_prepared_t *stmt;
-+
-+ apr_hash_this(hi, (void*) &label, NULL, (void*) &query);
-+
-+ if (!strcmp(query, "")) {
-+ continue;
-+ }
-
-- for (p = svr->prepared; p; p = p->next) {
- stmt = NULL;
-- if (apr_dbd_prepare(dbd->driver, pool, dbd->handle, p->query,
-- p->label, &stmt) == 0) {
-- apr_hash_set(dbd->prepared, p->label, APR_HASH_KEY_STRING, stmt);
-+ if (apr_dbd_prepare(rec->driver, pool, rec->handle, query,
-+ label, &stmt)) {
-+ rv = APR_EGENERAL;
- }
- else {
-- ret = APR_EGENERAL;
-+ apr_hash_set(rec->prepared, label, APR_HASH_KEY_STRING, stmt);
- }
- }
-- return ret;
-+
-+ return rv;
- }
--/************ svr cfg: manage db connection pool ****************/
-+
-+static apr_status_t dbd_close(void *data)
-+{
-+ ap_dbd_t *rec = data;
-+
-+ return apr_dbd_close(rec->driver, rec->handle);
-+}
-+
-+#if APR_HAS_THREADS
-+static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool)
-+{
-+ dbd_group_t *group = params;
-+
-+ if (!group->destroyed) {
-+ ap_dbd_t *rec = data;
-+
-+ apr_pool_destroy(rec->pool);
-+ }
-+
-+ return APR_SUCCESS;
-+}
-+#endif
-+
- /* an apr_reslist_constructor for SQL connections
- * Also use this for opening in non-reslist modes, since it gives
- * us all the error-handling in one place.
- */
--static apr_status_t dbd_construct(void **db, void *params, apr_pool_t *pool)
-+static apr_status_t dbd_construct(void **data_ptr,
-+ void *params, apr_pool_t *pool)
- {
-- svr_cfg *svr = (svr_cfg*) params;
-- ap_dbd_t *rec = apr_pcalloc(pool, sizeof(ap_dbd_t));
-+ dbd_group_t *group = params;
-+ dbd_cfg_t *cfg = group->cfg;
-+ apr_pool_t *rec_pool, *prepared_pool;
-+ ap_dbd_t *rec;
- apr_status_t rv;
-
-- /* this pool is mostly so dbd_close can destroy the prepared stmts */
-- rv = apr_pool_create(&rec->pool, pool);
-+ rv = apr_pool_create(&rec_pool, pool);
- if (rv != APR_SUCCESS) {
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool,
-- "DBD: Failed to create memory pool");
-+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,
-+ "DBD: Failed to create memory pool");
-+ return rv;
- }
-
--/* The driver is loaded at config time now, so this just checks a hash.
-- * If that changes, the driver DSO could be registered to unload against
-- * our pool, which is probably not what we want. Error checking isn't
-- * necessary now, but in case that changes in the future ...
-- */
-- rv = apr_dbd_get_driver(rec->pool, svr->name, &rec->driver);
-- switch (rv) {
-- case APR_ENOTIMPL:
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: driver for %s not available", svr->name);
-- return rv;
-- case APR_EDSOOPEN:
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: can't find driver for %s", svr->name);
-- return rv;
-- case APR_ESYMNOTFOUND:
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: driver for %s is invalid or corrupted", svr->name);
-- return rv;
-- default:
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: mod_dbd not compatible with apr in get_driver");
-+ rec = apr_pcalloc(rec_pool, sizeof(ap_dbd_t));
-+
-+ rec->pool = rec_pool;
-+
-+ /* The driver is loaded at config time now, so this just checks a hash.
-+ * If that changes, the driver DSO could be registered to unload against
-+ * our pool, which is probably not what we want. Error checking isn't
-+ * necessary now, but in case that changes in the future ...
-+ */
-+ rv = apr_dbd_get_driver(rec->pool, cfg->name, &rec->driver);
-+ if (rv != APR_SUCCESS) {
-+ switch (rv) {
-+ case APR_ENOTIMPL:
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: driver for %s not available", cfg->name);
-+ break;
-+ case APR_EDSOOPEN:
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: can't find driver for %s", cfg->name);
-+ break;
-+ case APR_ESYMNOTFOUND:
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: driver for %s is invalid or corrupted",
-+ cfg->name);
-+ break;
-+ default:
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: mod_dbd not compatible with APR in get_driver");
-+ break;
-+ }
-+
-+ apr_pool_destroy(rec->pool);
- return rv;
-- case APR_SUCCESS:
-- break;
- }
-
-- rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec->handle);
-- switch (rv) {
-- case APR_EGENERAL:
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: Can't connect to %s", svr->name);
-+ rv = apr_dbd_open(rec->driver, rec->pool, cfg->params, &rec->handle);
-+ if (rv != APR_SUCCESS) {
-+ switch (rv) {
-+ case APR_EGENERAL:
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: Can't connect to %s", cfg->name);
-+ break;
-+ default:
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: mod_dbd not compatible with APR in open");
-+ break;
-+ }
-+
-+ apr_pool_destroy(rec->pool);
- return rv;
-- default:
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: mod_dbd not compatible with apr in open");
-+ }
-+
-+ apr_pool_cleanup_register(rec->pool, rec, dbd_close,
-+ apr_pool_cleanup_null);
-+
-+ /* we use a sub-pool for the prepared statements for each connection so
-+ * that they will be cleaned up first, before the connection is closed
-+ */
-+ rv = apr_pool_create(&prepared_pool, rec->pool);
-+ if (rv != APR_SUCCESS) {
-+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server,
-+ "DBD: Failed to create memory pool");
-+
-+ apr_pool_destroy(rec->pool);
- return rv;
-- case APR_SUCCESS:
-- break;
- }
-- *db = rec;
-- rv = dbd_prepared_init(rec->pool, svr, rec);
-+
-+ rv = dbd_prepared_init(prepared_pool, cfg, rec);
- if (rv != APR_SUCCESS) {
- const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv);
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool,
-- "DBD: failed to initialise prepared SQL statements: %s",
-- (errmsg ? errmsg : "[???]"));
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server,
-+ "DBD: failed to prepare SQL statements: %s",
-+ (errmsg ? errmsg : "[???]"));
-+
-+ apr_pool_destroy(rec->pool);
-+ return rv;
- }
-- return rv;
--}
--static apr_status_t dbd_close(void *CONN)
--{
-- ap_dbd_t *conn = CONN;
-- apr_status_t rv = apr_dbd_close(conn->driver, conn->handle);
-- apr_pool_destroy(conn->pool);
-- return rv;
-+
-+ *data_ptr = rec;
-+
-+ return APR_SUCCESS;
- }
-+
- #if APR_HAS_THREADS
--static apr_status_t dbd_destruct(void *sql, void *params, apr_pool_t *pool)
-+static apr_status_t dbd_destroy(void *data)
- {
-- return dbd_close(sql);
-+ dbd_group_t *group = data;
-+
-+ group->destroyed = 1;
-+
-+ return APR_SUCCESS;
- }
-
--static apr_status_t dbd_setup(apr_pool_t *pool, svr_cfg *svr)
-+static apr_status_t dbd_setup(server_rec *s, dbd_group_t *group)
- {
-+ dbd_cfg_t *cfg = group->cfg;
- apr_status_t rv;
-
-- /* create a pool just for the reslist from a process-lifetime pool;
-- * that pool (s->process->pool in the dbd_setup_lock case,
-- * whatever was passed to ap_run_child_init in the dbd_setup_init case)
-- * will be shared with other threads doing other non-mod_dbd things
-- * so we can't use it for the reslist directly
-+ /* We create the reslist using a sub-pool of the pool passed to our
-+ * child_init hook. No other threads can be here because we're
-+ * either in the child_init phase or dbd_setup_lock() acquired our mutex.
-+ * No other threads will use this sub-pool after this, except via
-+ * reslist calls, which have an internal mutex.
-+ *
-+ * We need to short-circuit the cleanup registered internally by
-+ * apr_reslist_create(). We do this by registering dbd_destroy()
-+ * as a cleanup afterwards, so that it will run before the reslist's
-+ * internal cleanup.
-+ *
-+ * If we didn't do this, then we could free memory twice when the pool
-+ * was destroyed. When apr_pool_destroy() runs, it first destroys all
-+ * all the per-connection sub-pools created in dbd_construct(), and
-+ * then it runs the reslist's cleanup. The cleanup calls dbd_destruct()
-+ * on each resource, which would then attempt to destroy the sub-pools
-+ * a second time.
- */
-- rv = apr_pool_create(&svr->pool, pool);
-+ rv = apr_reslist_create(&group->reslist,
-+ cfg->nmin, cfg->nkeep, cfg->nmax,
-+ apr_time_from_sec(cfg->exptime),
-+ dbd_construct, dbd_destruct, group,
-+ group->pool);
- if (rv != APR_SUCCESS) {
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool,
-- "DBD: Failed to create reslist memory pool");
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-+ "DBD: failed to initialise");
- return rv;
- }
-
-- rv = apr_reslist_create(&svr->dbpool, svr->nmin, svr->nkeep, svr->nmax,
-- apr_time_from_sec(svr->exptime),
-- dbd_construct, dbd_destruct, svr, svr->pool);
-- if (rv == APR_SUCCESS) {
-- apr_pool_cleanup_register(svr->pool, svr->dbpool,
-- (void*)apr_reslist_destroy,
-- apr_pool_cleanup_null);
-- }
-- else {
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, svr->pool,
-- "DBD: failed to initialise");
-- apr_pool_destroy(svr->pool);
-- svr->pool = NULL;
-- }
-+ apr_pool_cleanup_register(group->pool, group, dbd_destroy,
-+ apr_pool_cleanup_null);
-
-- return rv;
-+ return APR_SUCCESS;
- }
-+#endif
-+
- static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s)
- {
-- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
-- apr_status_t rv;
-+ dbd_group_t *group;
-+ apr_status_t rv = APR_SUCCESS;
-
-- /* dbd_setup in 2.2.3 and under was causing spurious error messages
-- * when dbd isn't configured. We can stop that with a quick check here
-- * together with a similar check in ap_dbd_open (where being
-- * unconfigured is a genuine error that must be reported).
-- */
-- if (svr->name == no_dbdriver) {
-- return APR_SUCCESS;
-- }
-+ for (group = group_list; group; group = group->next) {
-+ apr_status_t rv2;
-
-- if (!svr->persist) {
-- return APR_SUCCESS;
-- }
-+ rv2 = apr_pool_create(&group->pool, pool);
-+ if (rv2 != APR_SUCCESS) {
-+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,
-+ "DBD: Failed to create reslist cleanup memory pool");
-+ return rv2;
-+ }
-
-- rv = dbd_setup(pool, svr);
-- if (rv == APR_SUCCESS) {
-- return rv;
-- }
-+#if APR_HAS_THREADS
-+ rv2 = dbd_setup(s, group);
-+ if (rv2 == APR_SUCCESS) {
-+ continue;
-+ }
-+ else if (rv == APR_SUCCESS) {
-+ rv = rv2;
-+ }
-
-- /* we failed, so create a mutex so that subsequent competing callers
-- * to ap_dbd_open can serialize themselves while they retry
-- */
-- rv = apr_thread_mutex_create(&svr->mutex, APR_THREAD_MUTEX_DEFAULT, pool);
-- if (rv != APR_SUCCESS) {
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool,
-- "DBD: Failed to create thread mutex");
-+ /* we failed, so create a mutex so that subsequent competing callers
-+ * to ap_dbd_open can serialize themselves while they retry
-+ */
-+ rv2 = apr_thread_mutex_create(&group->mutex,
-+ APR_THREAD_MUTEX_DEFAULT, pool);
-+ if (rv2 != APR_SUCCESS) {
-+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s,
-+ "DBD: Failed to create thread mutex");
-+ return rv2;
-+ }
-+#endif
- }
-+
- return rv;
- }
--static apr_status_t dbd_setup_lock(apr_pool_t *pool, server_rec *s)
-+
-+#if APR_HAS_THREADS
-+static apr_status_t dbd_setup_lock(server_rec *s, dbd_group_t *group)
- {
-- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
-- apr_status_t rv, rv2 = APR_SUCCESS;
-+ apr_status_t rv = APR_SUCCESS, rv2;
-
- /* several threads could be here at the same time, all trying to
- * initialize the reslist because dbd_setup_init failed to do so
- */
-- if (!svr->mutex) {
-+ if (!group->mutex) {
- /* we already logged an error when the mutex couldn't be created */
- return APR_EGENERAL;
- }
-
-- rv = apr_thread_mutex_lock(svr->mutex);
-- if (rv != APR_SUCCESS) {
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool,
-- "DBD: Failed to acquire thread mutex");
-- return rv;
-- }
--
-- if (!svr->dbpool) {
-- rv2 = dbd_setup(s->process->pool, svr);
-- }
--
-- rv = apr_thread_mutex_unlock(svr->mutex);
-- if (rv != APR_SUCCESS) {
-- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool,
-- "DBD: Failed to release thread mutex");
-- if (rv2 == APR_SUCCESS) {
-- rv2 = rv;
-+ rv2 = apr_thread_mutex_lock(group->mutex);
-+ if (rv2 != APR_SUCCESS) {
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
-+ "DBD: Failed to acquire thread mutex");
-+ return rv2;
-+ }
-+
-+ if (!group->reslist) {
-+ rv = dbd_setup(s, group);
-+ }
-+
-+ rv2 = apr_thread_mutex_unlock(group->mutex);
-+ if (rv2 != APR_SUCCESS) {
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s,
-+ "DBD: Failed to release thread mutex");
-+ if (rv == APR_SUCCESS) {
-+ rv = rv2;
- }
- }
-- return rv2;
-+
-+ return rv;
- }
- #endif
-
--
- /* Functions we export for modules to use:
- - open acquires a connection from the pool (opens one if necessary)
- - close releases it back in to the pool
- */
--DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *sql)
-+DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *rec)
- {
- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
-- if (!svr->persist) {
-- dbd_close((void*) sql);
-+
-+ if (!svr->cfg->persist) {
-+ apr_pool_destroy(rec->pool);
- }
- #if APR_HAS_THREADS
- else {
-- apr_reslist_release(svr->dbpool, sql);
-+ apr_reslist_release(svr->group->reslist, rec);
- }
- #endif
- }
--#define arec ((ap_dbd_t*)rec)
--#if APR_HAS_THREADS
-+
-+static apr_status_t dbd_check(apr_pool_t *pool, server_rec *s, ap_dbd_t *rec)
-+{
-+ svr_cfg *svr;
-+ apr_status_t rv = apr_dbd_check_conn(rec->driver, pool, rec->handle);
-+ const char *errmsg;
-+
-+ if ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) {
-+ return APR_SUCCESS;
-+ }
-+
-+ /* we don't have a driver-specific error code, so we'll just pass
-+ * a "success" value and rely on the driver to ignore it
-+ */
-+ errmsg = apr_dbd_error(rec->driver, rec->handle, 0);
-+ if (!errmsg) {
-+ errmsg = "(unknown)";
-+ }
-+
-+ svr = ap_get_module_config(s->module_config, &dbd_module);
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-+ "DBD [%s] Error: %s", svr->cfg->name, errmsg);
-+ return rv;
-+}
-+
- DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)
- {
-- void *rec = NULL;
- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
-- apr_status_t rv = APR_SUCCESS;
-- const char *errmsg;
-+ dbd_group_t *group = svr->group;
-+ dbd_cfg_t *cfg = svr->cfg;
-+ ap_dbd_t *rec = NULL;
-+#if APR_HAS_THREADS
-+ apr_status_t rv;
-+#endif
-
- /* If nothing is configured, we shouldn't be here */
-- if (svr->name == no_dbdriver) {
-- ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "DBD: not configured");
-+ if (cfg->name == no_dbdriver) {
-+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured");
- return NULL;
- }
-
-- if (!svr->persist) {
-+ if (!cfg->persist) {
- /* Return a once-only connection */
-- rv = dbd_construct(&rec, svr, s->process->pool);
-- return (rv == APR_SUCCESS) ? arec : NULL;
-+ group = apr_pcalloc(pool, sizeof(dbd_group_t));
-+
-+ group->cfg = cfg;
-+
-+ dbd_construct((void*) &rec, group, pool);
-+ return rec;
- }
-
-- if (!svr->dbpool) {
-- if (dbd_setup_lock(pool, s) != APR_SUCCESS) {
-+#if APR_HAS_THREADS
-+ if (!group->reslist) {
-+ if (dbd_setup_lock(s, group) != APR_SUCCESS) {
- return NULL;
- }
- }
-- rv = apr_reslist_acquire(svr->dbpool, &rec);
-+
-+ rv = apr_reslist_acquire(group->reslist, (void*) &rec);
- if (rv != APR_SUCCESS) {
-- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool,
-- "Failed to acquire DBD connection from pool!");
-+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
-+ "Failed to acquire DBD connection from pool!");
- return NULL;
- }
-- rv = apr_dbd_check_conn(arec->driver, pool, arec->handle);
-- if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
-- errmsg = apr_dbd_error(arec->driver, arec->handle, rv);
-- if (!errmsg) {
-- errmsg = "(unknown)";
-- }
-- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool,
-- "DBD[%s] Error: %s", svr->name, errmsg );
-- apr_reslist_invalidate(svr->dbpool, rec);
-+
-+ if (dbd_check(pool, s, rec) != APR_SUCCESS) {
-+ apr_reslist_invalidate(group->reslist, rec);
- return NULL;
- }
-- return arec;
--}
- #else
--DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)
--{
-- apr_status_t rv = APR_SUCCESS;
-- const char *errmsg;
-- void *rec = NULL;
-- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module);
--
-- /* If nothing is configured, we shouldn't be here */
-- if (svr->name == no_dbdriver) {
-- ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "DBD: not configured");
-- return NULL;
-+ /* If we have a persistent connection and it's good, we'll use it;
-+ * since this is non-threaded, we can update without a mutex
-+ */
-+ rec = group->rec;
-+ if (rec) {
-+ if (dbd_check(pool, s, rec) != APR_SUCCESS) {
-+ apr_pool_destroy(rec->pool);
-+ rec = NULL;
-+ }
- }
-
-- if (!svr->persist) {
-- /* Return a once-only connection */
-- rv = dbd_construct(&rec, svr, s->process->pool);
-- return (rv == APR_SUCCESS) ? arec : NULL;
-+ /* We don't have a connection right now, so we'll open one */
-+ if (!rec) {
-+ dbd_construct((void*) &rec, group, group->pool);
-+ group->rec = rec;
- }
-+#endif
-
--/* since we're in nothread-land, we can mess with svr->conn with impunity */
--/* If we have a persistent connection and it's good, we'll use it */
-- if (svr->conn) {
-- rv = apr_dbd_check_conn(svr->conn->driver, pool, svr->conn->handle);
-- if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
-- errmsg = apr_dbd_error(arec->driver, arec->handle, rv);
-- if (!errmsg) {
-- errmsg = "(unknown)";
-- }
-- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool,
-- "DBD[%s] Error: %s", svr->name, errmsg);
-- svr->conn = NULL;
-- }
-- }
--/* We don't have a connection right now, so we'll open one */
-- if (!svr->conn) {
-- if (dbd_construct(&rec, svr, s->process->pool) == APR_SUCCESS) {
-- svr->conn = arec ;
-- apr_pool_cleanup_register(s->process->pool, svr->conn,
-- dbd_close, apr_pool_cleanup_null);
-- }
-- }
-- return svr->conn;
-+ return rec;
- }
--#endif
-+
- #if APR_HAS_THREADS
- typedef struct {
-- ap_dbd_t *conn;
-- apr_reslist_t *dbpool;
--} dbd_pool_rec;
--static apr_status_t dbd_release(void *REQ)
-+ ap_dbd_t *rec;
-+ apr_reslist_t *reslist;
-+} dbd_acquire_t;
-+
-+static apr_status_t dbd_release(void *data)
- {
-- dbd_pool_rec *req = REQ;
-- apr_reslist_release(req->dbpool, req->conn);
-+ dbd_acquire_t *acq = data;
-+ apr_reslist_release(acq->reslist, acq->rec);
- return APR_SUCCESS;
- }
-+
- DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r)
- {
-- svr_cfg *svr;
-- dbd_pool_rec *req;
-+ dbd_acquire_t *acq;
-
- while (!ap_is_initial_req(r)) {
- if (r->prev) {
-@@ -557,54 +812,52 @@ DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ac
- }
- }
-
-- req = ap_get_module_config(r->request_config, &dbd_module);
-- if (!req) {
-- req = apr_palloc(r->pool, sizeof(dbd_pool_rec));
-- req->conn = ap_dbd_open(r->pool, r->server);
-- if (req->conn) {
-- svr = ap_get_module_config(r->server->module_config, &dbd_module);
-- ap_set_module_config(r->request_config, &dbd_module, req);
-- if (svr->persist) {
-- req->dbpool = svr->dbpool;
-- apr_pool_cleanup_register(r->pool, req, dbd_release,
-- apr_pool_cleanup_null);
-- }
-- else {
-- apr_pool_cleanup_register(r->pool, req->conn, dbd_close,
-+ acq = ap_get_module_config(r->request_config, &dbd_module);
-+ if (!acq) {
-+ acq = apr_palloc(r->pool, sizeof(dbd_acquire_t));
-+ acq->rec = ap_dbd_open(r->pool, r->server);
-+ if (acq->rec) {
-+ svr_cfg *svr = ap_get_module_config(r->server->module_config,
-+ &dbd_module);
-+
-+ ap_set_module_config(r->request_config, &dbd_module, acq);
-+ if (svr->cfg->persist) {
-+ acq->reslist = svr->group->reslist;
-+ apr_pool_cleanup_register(r->pool, acq, dbd_release,
- apr_pool_cleanup_null);
- }
- }
- }
-- return req->conn;
-+
-+ return acq->rec;
- }
-+
- DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c)
- {
-- svr_cfg *svr;
-- dbd_pool_rec *req = ap_get_module_config(c->conn_config, &dbd_module);
-- if (!req) {
-- req = apr_palloc(c->pool, sizeof(dbd_pool_rec));
-- req->conn = ap_dbd_open(c->pool, c->base_server);
-- if (req->conn) {
-- svr = ap_get_module_config(c->base_server->module_config, &dbd_module);
-- ap_set_module_config(c->conn_config, &dbd_module, req);
-- if (svr->persist) {
-- req->dbpool = svr->dbpool;
-- apr_pool_cleanup_register(c->pool, req, dbd_release,
-- apr_pool_cleanup_null);
-- }
-- else {
-- apr_pool_cleanup_register(c->pool, req->conn, dbd_close,
-+ dbd_acquire_t *acq = ap_get_module_config(c->conn_config, &dbd_module);
-+
-+ if (!acq) {
-+ acq = apr_palloc(c->pool, sizeof(dbd_acquire_t));
-+ acq->rec = ap_dbd_open(c->pool, c->base_server);
-+ if (acq->rec) {
-+ svr_cfg *svr = ap_get_module_config(c->base_server->module_config,
-+ &dbd_module);
-+
-+ ap_set_module_config(c->conn_config, &dbd_module, acq);
-+ if (svr->cfg->persist) {
-+ acq->reslist = svr->group->reslist;
-+ apr_pool_cleanup_register(c->pool, acq, dbd_release,
- apr_pool_cleanup_null);
- }
- }
- }
-- return req->conn;
-+
-+ return acq->rec;
- }
- #else
- DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r)
- {
-- svr_cfg *svr;
-- ap_dbd_t *ret;
-+ ap_dbd_t *rec;
-
- while (!ap_is_initial_req(r)) {
- if (r->prev) {
-@@ -615,80 +868,54 @@ DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ac
- }
- }
-
-- ret = ap_get_module_config(r->request_config, &dbd_module);
-- if (!ret) {
-- svr = ap_get_module_config(r->server->module_config, &dbd_module);
-- ret = ap_dbd_open(r->pool, r->server);
-- if (ret) {
-- ap_set_module_config(r->request_config, &dbd_module, ret);
-- if (!svr->persist) {
-- apr_pool_cleanup_register(r->pool, svr->conn, dbd_close,
-- apr_pool_cleanup_null);
-- }
-- /* if persist then dbd_open registered cleanup on proc pool */
-+ rec = ap_get_module_config(r->request_config, &dbd_module);
-+ if (!rec) {
-+ rec = ap_dbd_open(r->pool, r->server);
-+ if (rec) {
-+ ap_set_module_config(r->request_config, &dbd_module, rec);
- }
- }
-- return ret;
-+
-+ return rec;
- }
-+
- DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c)
- {
-- svr_cfg *svr;
-- ap_dbd_t *ret = ap_get_module_config(c->conn_config, &dbd_module);
-- if (!ret) {
-- svr = ap_get_module_config(c->base_server->module_config, &dbd_module);
-- ret = ap_dbd_open(c->pool, c->base_server);
-- if (ret) {
-- ap_set_module_config(c->conn_config, &dbd_module, ret);
-- if (!svr->persist) {
-- apr_pool_cleanup_register(c->pool, svr->conn, dbd_close,
-- apr_pool_cleanup_null);
-- }
-- /* if persist then dbd_open registered cleanup on proc pool */
-+ ap_dbd_t *rec = ap_get_module_config(c->conn_config, &dbd_module);
-+
-+ if (!rec) {
-+ rec = ap_dbd_open(c->pool, c->base_server);
-+ if (rec) {
-+ ap_set_module_config(c->conn_config, &dbd_module, rec);
- }
- }
-- return ret;
-+
-+ return rec;
- }
- #endif
-
--static int dbd_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
--{
-- dbd_prepared_defns = apr_hash_make(ptemp);
-- return OK;
--}
--static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog,
-- apr_pool_t *ptemp, server_rec *s)
--{
-- svr_cfg *svr;
-- server_rec *sp;
-- for (sp = s; sp; sp = sp->next) {
-- const char *key = apr_psprintf(s->process->pool, "%pp", s);
-- svr = ap_get_module_config(sp->module_config, &dbd_module);
-- svr->prepared = apr_hash_get(dbd_prepared_defns, key,
-- APR_HASH_KEY_STRING);
-- }
-- return OK;
--}
- static void dbd_hooks(apr_pool_t *pool)
- {
--#if APR_HAS_THREADS
-+ ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
-+ ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_child_init((void*)dbd_setup_init, NULL, NULL, APR_HOOK_MIDDLE);
--#endif
-+
-+ APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare);
- APR_REGISTER_OPTIONAL_FN(ap_dbd_open);
- APR_REGISTER_OPTIONAL_FN(ap_dbd_close);
- APR_REGISTER_OPTIONAL_FN(ap_dbd_acquire);
- APR_REGISTER_OPTIONAL_FN(ap_dbd_cacquire);
-- APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare);
-+
- apr_dbd_init(pool);
-- ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
-- ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- }
-
- module AP_MODULE_DECLARE_DATA dbd_module = {
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
-- dbd_cfg,
-- dbd_merge,
-+ create_dbd_config,
-+ merge_dbd_config,
- dbd_cmds,
- dbd_hooks
- };
-+
diff --git a/2.2/patches/20_all_peruser_0.2.1.patch b/2.2/patches/20_all_peruser_0.2.2.patch
index 93d2028..adcfd14 100644
--- a/2.2/patches/20_all_peruser_0.2.1.patch
+++ b/2.2/patches/20_all_peruser_0.2.2.patch
@@ -1,6 +1,6 @@
diff -Nur httpd-2.2.3/server/mpm/config.m4 httpd-2.2.3-new/server/mpm/config.m4
--- httpd-2.2.3/server/mpm/config.m4 2005-10-30 10:05:26.000000000 -0700
-+++ httpd-2.2.3-new/server/mpm/config.m4 2007-02-05 06:47:03.000000000 -0700
++++ httpd-2.2.3-new/server/mpm/config.m4 2007-08-17 18:23:23.000000000 -0600
@@ -1,7 +1,7 @@
AC_MSG_CHECKING(which MPM to use)
AC_ARG_WITH(mpm,
@@ -21,7 +21,7 @@ diff -Nur httpd-2.2.3/server/mpm/config.m4 httpd-2.2.3-new/server/mpm/config.m4
return 1
diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/Makefile.in httpd-2.2.3-new/server/mpm/experimental/peruser/Makefile.in
--- httpd-2.2.3/server/mpm/experimental/peruser/Makefile.in 1969-12-31 17:00:00.000000000 -0700
-+++ httpd-2.2.3-new/server/mpm/experimental/peruser/Makefile.in 2007-02-05 06:47:03.000000000 -0700
++++ httpd-2.2.3-new/server/mpm/experimental/peruser/Makefile.in 2007-08-17 18:23:23.000000000 -0600
@@ -0,0 +1,5 @@
+
+LTLIBRARY_NAME = libperuser.la
@@ -30,14 +30,14 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/Makefile.in httpd-2.2.3-ne
+include $(top_srcdir)/build/ltlib.mk
diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/config.m4 httpd-2.2.3-new/server/mpm/experimental/peruser/config.m4
--- httpd-2.2.3/server/mpm/experimental/peruser/config.m4 1969-12-31 17:00:00.000000000 -0700
-+++ httpd-2.2.3-new/server/mpm/experimental/peruser/config.m4 2007-02-05 06:47:03.000000000 -0700
++++ httpd-2.2.3-new/server/mpm/experimental/peruser/config.m4 2007-08-17 18:23:23.000000000 -0600
@@ -0,0 +1,3 @@
+if test "$MPM_NAME" = "peruser" ; then
+ APACHE_FAST_OUTPUT(server/mpm/experimental/$MPM_NAME/Makefile)
+fi
diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm.h httpd-2.2.3-new/server/mpm/experimental/peruser/mpm.h
--- httpd-2.2.3/server/mpm/experimental/peruser/mpm.h 1969-12-31 17:00:00.000000000 -0700
-+++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm.h 2007-02-05 06:47:03.000000000 -0700
++++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm.h 2007-08-17 18:23:23.000000000 -0600
@@ -0,0 +1,103 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
@@ -144,7 +144,7 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm.h httpd-2.2.3-new/serv
+#endif /* APACHE_MPM_PERUSER_H */
diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.3-new/server/mpm/experimental/peruser/mpm_default.h
--- httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h 1969-12-31 17:00:00.000000000 -0700
-+++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm_default.h 2007-02-05 06:47:03.000000000 -0700
++++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm_default.h 2007-08-17 18:23:23.000000000 -0600
@@ -0,0 +1,110 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
@@ -258,8 +258,8 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.3-
+#endif /* AP_MPM_DEFAULT_H */
diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/server/mpm/experimental/peruser/peruser.c
--- httpd-2.2.3/server/mpm/experimental/peruser/peruser.c 1969-12-31 17:00:00.000000000 -0700
-+++ httpd-2.2.3-new/server/mpm/experimental/peruser/peruser.c 2007-02-05 07:16:52.000000000 -0700
-@@ -0,0 +1,3006 @@
++++ httpd-2.2.3-new/server/mpm/experimental/peruser/peruser.c 2007-08-17 18:23:59.000000000 -0600
+@@ -0,0 +1,3130 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
@@ -526,6 +526,16 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+
+typedef struct
+{
++ /* identification */
++ int id; /* index in child_info_table */
++ pid_t pid; /* process id */
++ int status; /* status of child */
++ int type; /* multiplexer or processor */
++ apr_time_t last_used;
++} child_grace_info_t;
++
++typedef struct
++{
+ apr_size_t num;
+} child_info_control;
+
@@ -535,7 +545,6 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ child_info_t *table;
+} child_info;
+
-+
+typedef struct
+{
+ server_env_t *senv;
@@ -555,6 +564,7 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ */
+static apr_size_t child_info_size;
+static child_info *child_info_image;
++static child_grace_info_t *child_grace_info_table;
+struct ap_ctable *ap_child_table;
+
+#define NUM_CHILDS (child_info_image != NULL ? child_info_image->control->num : 0)
@@ -617,6 +627,9 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+
+static int die_now = 0;
+
++int grace_children = 0;
++int grace_children_alive = 0;
++
+#ifdef GPROF
+/*
+ * change directory for gprof to plop the gmon.out file
@@ -2047,18 +2060,18 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ child_info_t *this;
+ child_info_t *new;
+
-+ if(NUM_CHILDS >= server_limit)
-+ {
-+ _DBG("Trying to use more child ID's than NumServers. "
-+ "Increase NumServers in your config file.");
-+ return NULL;
-+ }
-+
+ for(i = 0; i < NUM_CHILDS; i++)
+ {
+ if(CHILD_INFO_TABLE[i].pid == 0 &&
+ CHILD_INFO_TABLE[i].type == CHILD_TYPE_UNKNOWN) break;
+ }
++
++ if(i == NUM_CHILDS && NUM_CHILDS >= server_limit)
++ {
++ _DBG("Trying to use more child ID's than NumServers. "
++ "Increase NumServers in your config file.");
++ return NULL;
++ }
+
+ _DBG("cloning child #%d from #%d", i, my_child_num);
+
@@ -2289,8 +2302,48 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ ap_update_child_status_from_indexes(i, 0, SERVER_DEAD, NULL);
+ }
+ }
++
++ for(i=0;i<grace_children;i++) {
++ if (child_grace_info_table[i].pid > 0 &&
++ apr_time_sec(now - child_grace_info_table[i].last_used) > expire_timeout) {
++
++ _DBG("Killing a child from last graceful (pid=%d,childno=%d,last_used=%d)",
++ child_grace_info_table[i].pid, child_grace_info_table[i].id,
++ child_grace_info_table[i].last_used);
++
++ if(kill(child_grace_info_table[i].pid, SIGTERM) == -1)
++ {
++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
++ ap_server_conf, "kill SIGTERM");
++ }
++
++ /* We don't need to do remove_grace_child() here,
++ * because it will be automatically done once
++ * the child dies by ap_mpm_run() */
++ }
++ }
+}
+
++int remove_grace_child(int slot) {
++ if (slot < grace_children) {
++ child_grace_info_table[slot].id = 0;
++ child_grace_info_table[slot].pid = 0;
++ child_grace_info_table[slot].status = CHILD_STATUS_STANDBY;
++ child_grace_info_table[slot].type = CHILD_TYPE_UNKNOWN;
++ child_grace_info_table[slot].last_used = 0;
++ grace_children_alive--;
++
++ if (grace_children_alive <= 0) { /* All children have returned from graceful */
++ _DBG("Every child has returned from graceful restart - freeing child_grace_info_table");
++ grace_children_alive = 0;
++ is_graceful = 0;
++ grace_children = 0;
++ free(child_grace_info_table);
++ }
++ return 0;
++ }
++ return 1;
++}
+
+/*****************************************************************
+ * Executive routines.
@@ -2424,6 +2477,19 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ mpm_state = AP_MPMQ_STOPPING;
+ return 1;
+ }
++
++ if (grace_children > 0) {
++ for(i=0;i<grace_children;i++) {
++ if (child_grace_info_table[i].pid == pid.pid) {
++ break;
++ }
++ }
++ if (i != grace_children) {
++ _DBG("Child returned from graceful (%d)", i);
++ remove_grace_child(i);
++ continue;
++ }
++ }
+
+ /* non-fatal death... note that it's gone in the scoreboard. */
+ child_slot = find_child_by_pid(&pid);
@@ -2569,9 +2635,42 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ * gracefully dealing with existing request.
+ */
+
++ int alivechildren = 0;
++ int child_grace_info_size;
++ child_grace_info_t* old_grace_info;
++ void* mem;
++
+ for (i = 0; i < NUM_CHILDS; ++i)
+ {
+ ((ap_child_table[i].pid) && (ap_child_table[i].status = SERVER_DYING));
++
++ if (CHILD_INFO_TABLE[i].pid) {
++ alivechildren++;
++ }
++ }
++
++ _DBG("Initializing child_grace_info_table", 0);
++
++ if (alivechildren > 0) {
++ if (grace_children > 0) {
++ old_grace_info = child_grace_info_table;
++ _DBG("%d children still living from last graceful "
++ "- adding to new child_grace_info_table",
++ grace_children);
++ }
++
++ child_grace_info_table = (child_grace_info_t*)calloc(alivechildren+grace_children,
++ sizeof(child_grace_info_t));
++
++ if (grace_children > 0) {
++ for(i=0;i<grace_children;i++) {
++ child_grace_info_table[i] = old_grace_info[i];
++ }
++ grace_children = i;
++ free(old_grace_info);
++ }
++ else grace_children = 0;
++
+ }
+
+ /* give the children the signal to die */
@@ -2583,8 +2682,19 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
+ "write pipe_of_death");
+ }
++ if (CHILD_INFO_TABLE[i].pid) {
++ child_grace_info_table[grace_children].id = CHILD_INFO_TABLE[i].id;
++ child_grace_info_table[grace_children].pid = CHILD_INFO_TABLE[i].pid;
++ child_grace_info_table[grace_children].status = CHILD_INFO_TABLE[i].status;
++ child_grace_info_table[grace_children].type = CHILD_INFO_TABLE[i].type;
++ child_grace_info_table[grace_children].last_used = ap_scoreboard_image->servers[i][0].last_used;
++ grace_children++;
++ grace_children_alive++;
++ }
+ i++;
+ }
++ _DBG("Total children of %d leaving behind for graceful restart (%d living)",
++ grace_children, grace_children_alive);
+
+ for (i = 0; i < NUM_SENV; i++)
+ {
@@ -2654,9 +2764,9 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ return OK;
+}
+
++static int restart_num = 0;
+static int peruser_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
+{
-+ static int restart_num = 0;
+ int no_detach, debug, foreground, i;
+ int tmp_server_limit = DEFAULT_SERVER_LIMIT;
+ ap_directive_t *pdir;
@@ -2681,8 +2791,6 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+
+ /* sigh, want this only the second time around */
+ if (restart_num++ == 1) {
-+ is_graceful = 0;
-+
+ if (!one_process && !foreground) {
+ rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
+ : APR_PROC_DETACH_DAEMONIZE);
@@ -2952,6 +3060,22 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/
+ );
+ }
+ ap_rputs("</table>\n", r);
++
++ if (grace_children > 0) {
++ ap_rputs("<h2>peruser graceful children status</h2>\n", r);
++ ap_rprintf(r, "%d of total %d still living<br />\n", grace_children_alive, grace_children);
++ ap_rputs("<table border=\"0\">\n", r);
++ ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>TYPE</td></tr>\n", r);
++ for (x = 0; x < grace_children; x++) {
++ ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%12s</td></tr>\n",
++ child_grace_info_table[x].id,
++ child_grace_info_table[x].pid,
++ child_status_string(child_grace_info_table[x].status),
++ child_type_string(child_grace_info_table[x].type)
++ );
++ }
++ ap_rputs("</table>\n", r);
++ }
+ return OK;
+}
+
diff --git a/2.2/patches/21_all_itk_20070425-00.patch b/2.2/patches/21_all_itk_20070425-00.patch
index 449a5e1..58c9706 100644
--- a/2.2/patches/21_all_itk_20070425-00.patch
+++ b/2.2/patches/21_all_itk_20070425-00.patch
@@ -11,7 +11,7 @@ Index: httpd-2.2.4/server/mpm/config.m4
APACHE_MPM=$withval
],[
if test "x$APACHE_MPM" = "x"; then
-@@ -23,7 +23,7 @@ ap_mpm_is_threaded ()
+@@ -23,7 +23,7 @@
ap_mpm_is_experimental ()
{
@@ -20,7 +20,7 @@ Index: httpd-2.2.4/server/mpm/config.m4
return 0
else
return 1
-@@ -66,6 +66,11 @@ if ap_mpm_is_experimental; then
+@@ -66,6 +66,11 @@
else
MPM_SUBDIR_NAME=$MPM_NAME
fi
@@ -33,7 +33,6 @@ Index: httpd-2.2.4/server/mpm/config.m4
MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
Index: httpd-2.2.4/server/mpm/experimental/itk/config.m4
-===================================================================
--- /dev/null
+++ httpd-2.2.4/server/mpm/experimental/itk/config.m4
@@ -0,0 +1,3 @@
@@ -41,7 +40,6 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/config.m4
+ APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile)
+fi
Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c
-===================================================================
--- /dev/null
+++ httpd-2.2.4/server/mpm/experimental/itk/itk.c
@@ -0,0 +1,1682 @@
@@ -1246,7 +1244,7 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c
+ for (index = 0; index < ap_daemons_limit; ++index) {
+ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
+ /* Ask each child to close its listeners. */
-+ kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
++ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
+ active_children++;
+ }
+ }
@@ -1284,13 +1282,13 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c
+
+ active_children = 0;
+ for (index = 0; index < ap_daemons_limit; ++index) {
-+ if (MPM_CHILD_PID(index) != 0) {
-+ if (kill(MPM_CHILD_PID(index), 0) == 0) {
++ //if (MPM_CHILD_PID(index) != 0) {
++ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
+ }
-+ }
++ //}
+ }
+ } while (!shutdown_pending && active_children &&
+ (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
@@ -1341,7 +1339,7 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c
+ * piped loggers, etc. They almost certainly won't handle
+ * it gracefully.
+ */
-+ kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
++ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
+ }
+ }
+ }
@@ -1738,7 +1736,6 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/Makefile.in
+
+include $(top_srcdir)/build/ltlib.mk
Index: httpd-2.2.4/server/mpm/experimental/itk/mpm_default.h
-===================================================================
--- /dev/null
+++ httpd-2.2.4/server/mpm/experimental/itk/mpm_default.h
@@ -0,0 +1,77 @@
@@ -1820,7 +1817,6 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/mpm_default.h
+#endif /* AP_MPM_DEFAULT_H */
+/** @} */
Index: httpd-2.2.4/server/mpm/experimental/itk/mpm.h
-===================================================================
--- /dev/null
+++ httpd-2.2.4/server/mpm/experimental/itk/mpm.h
@@ -0,0 +1,65 @@
diff --git a/2.2/patches/80_all_CVE-2006-5752.patch b/2.2/patches/80_all_CVE-2006-5752.patch
deleted file mode 100644
index cbf3297..0000000
--- a/2.2/patches/80_all_CVE-2006-5752.patch
+++ /dev/null
@@ -1,40 +0,0 @@
---- httpd-2.2.3/modules/generators/mod_status.c.cve5752
-+++ httpd-2.2.3/modules/generators/mod_status.c
-@@ -270,7 +270,7 @@
- if (r->method_number != M_GET)
- return DECLINED;
-
-- ap_set_content_type(r, "text/html");
-+ ap_set_content_type(r, "text/html; charset=ISO-8859-1");
-
- /*
- * Simple table-driven form data set parser that lets you alter the header
-@@ -299,7 +299,7 @@
- no_table_report = 1;
- break;
- case STAT_OPT_AUTO:
-- ap_set_content_type(r, "text/plain");
-+ ap_set_content_type(r, "text/plain; charset=ISO-8859-1");
- short_report = 1;
- break;
- }
-@@ -673,7 +673,8 @@
- ap_escape_html(r->pool,
- ws_record->client),
- ap_escape_html(r->pool,
-- ws_record->request),
-+ ap_escape_logitem(r->pool,
-+ ws_record->request)),
- ap_escape_html(r->pool,
- ws_record->vhost));
- }
-@@ -763,7 +764,8 @@
- ap_escape_html(r->pool,
- ws_record->vhost),
- ap_escape_html(r->pool,
-- ws_record->request));
-+ ap_escape_logitem(r->pool,
-+ ws_record->request)));
- } /* no_table_report */
- } /* for (j...) */
- } /* for (i...) */
diff --git a/2.2/patches/81_all_CVE-2007-1862.patch b/2.2/patches/81_all_CVE-2007-1862.patch
deleted file mode 100644
index 17e6cc5..0000000
--- a/2.2/patches/81_all_CVE-2007-1862.patch
+++ /dev/null
@@ -1,51 +0,0 @@
---- httpd-2.2.4/modules/cache/mod_mem_cache.c.cve1862
-+++ httpd-2.2.4/modules/cache/mod_mem_cache.c
-@@ -539,12 +539,28 @@
- return OK;
- }
-
-+static apr_table_t *deep_table_copy(apr_pool_t *p, const apr_table_t *table)
-+{
-+ const apr_array_header_t *array = apr_table_elts(table);
-+ apr_table_entry_t *elts = (apr_table_entry_t *) array->elts;
-+ apr_table_t *copy = apr_table_make(p, array->nelts);
-+ int i;
-+
-+ for (i = 0; i < array->nelts; i++) {
-+ if (elts[i].key) {
-+ apr_table_add(copy, elts[i].key, elts[i].val);
-+ }
-+ }
-+
-+ return copy;
-+}
-+
- static apr_status_t recall_headers(cache_handle_t *h, request_rec *r)
- {
- mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj;
-
-- h->req_hdrs = apr_table_copy(r->pool, mobj->req_hdrs);
-- h->resp_hdrs = apr_table_copy(r->pool, mobj->header_out);
-+ h->req_hdrs = deep_table_copy(r->pool, mobj->req_hdrs);
-+ h->resp_hdrs = deep_table_copy(r->pool, mobj->header_out);
-
- return OK;
- }
-@@ -585,7 +601,7 @@
- * - The original response headers (for returning with a cached response)
- * - The body of the message
- */
-- mobj->req_hdrs = apr_table_copy(mobj->pool, r->headers_in);
-+ mobj->req_hdrs = deep_table_copy(mobj->pool, r->headers_in);
-
- /* Precompute how much storage we need to hold the headers */
- headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out,
-@@ -599,7 +615,7 @@
- }
-
- headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out);
-- mobj->header_out = apr_table_copy(mobj->pool, headers_out);
-+ mobj->header_out = deep_table_copy(mobj->pool, headers_out);
-
- /* Init the info struct */
- obj->info.status = info->status;
diff --git a/2.2/patches/82_all_CVE-2007-1863.patch b/2.2/patches/82_all_CVE-2007-1863.patch
deleted file mode 100644
index 41c3ba7..0000000
--- a/2.2/patches/82_all_CVE-2007-1863.patch
+++ /dev/null
@@ -1,74 +0,0 @@
---- httpd-2.2.3/modules/cache/cache_util.c.cve1863
-+++ httpd-2.2.3/modules/cache/cache_util.c
-@@ -231,7 +231,8 @@
- age = ap_cache_current_age(info, age_c, r->request_time);
-
- /* extract s-maxage */
-- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)) {
-+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)
-+ && val != NULL) {
- smaxage = apr_atoi64(val);
- }
- else {
-@@ -240,7 +241,8 @@
-
- /* extract max-age from request */
- if (!conf->ignorecachecontrol
-- && cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)) {
-+ && cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)
-+ && val != NULL) {
- maxage_req = apr_atoi64(val);
- }
- else {
-@@ -248,7 +250,8 @@
- }
-
- /* extract max-age from response */
-- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)) {
-+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)
-+ && val != NULL) {
- maxage_cresp = apr_atoi64(val);
- }
- else {
-@@ -270,7 +273,20 @@
-
- /* extract max-stale */
- if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-stale", &val)) {
-- maxstale = apr_atoi64(val);
-+ if(val != NULL) {
-+ maxstale = apr_atoi64(val);
-+ }
-+ else {
-+ /*
-+ * If no value is assigned to max-stale, then the client is willing
-+ * to accept a stale response of any age (RFC2616 14.9.3). We will
-+ * set it to one year in this case as this situation is somewhat
-+ * similar to a "never expires" Expires header (RFC2616 14.21)
-+ * which is set to a date one year from the time the response is
-+ * sent in this case.
-+ */
-+ maxstale = APR_INT64_C(86400*365);
-+ }
- }
- else {
- maxstale = 0;
-@@ -278,7 +294,8 @@
-
- /* extract min-fresh */
- if (!conf->ignorecachecontrol
-- && cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)) {
-+ && cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)
-+ && val != NULL) {
- minfresh = apr_atoi64(val);
- }
- else {
-@@ -407,6 +424,9 @@
- next - val_start);
- }
- }
-+ else {
-+ *val = NULL;
-+ }
- }
- return 1;
- }
diff --git a/2.2/patches/83_all_CVE-2007-3304.patch b/2.2/patches/83_all_CVE-2007-3304.patch
deleted file mode 100644
index 7337d6a..0000000
--- a/2.2/patches/83_all_CVE-2007-3304.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-Index: httpd-2.2.4/server/mpm/prefork/prefork.c
-===================================================================
---- httpd-2.2.4.orig/server/mpm/prefork/prefork.c
-+++ httpd-2.2.4/server/mpm/prefork/prefork.c
-@@ -1127,7 +1127,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
- for (index = 0; index < ap_daemons_limit; ++index) {
- if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
- /* Ask each child to close its listeners. */
-- kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
-+ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
- active_children++;
- }
- }
-@@ -1165,12 +1165,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
-
- active_children = 0;
- for (index = 0; index < ap_daemons_limit; ++index) {
-- if (MPM_CHILD_PID(index) != 0) {
-- if (kill(MPM_CHILD_PID(index), 0) == 0) {
-- active_children = 1;
-- /* Having just one child is enough to stay around */
-- break;
-- }
-+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
-+ active_children = 1;
-+ /* Having just one child is enough to stay around */
-+ break;
- }
- }
- } while (!shutdown_pending && active_children &&
-@@ -1222,7 +1220,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
- * piped loggers, etc. They almost certainly won't handle
- * it gracefully.
- */
-- kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
-+ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
- }
- }
- }
-Index: httpd-2.2.4/server/mpm/worker/worker.c
-===================================================================
---- httpd-2.2.4.orig/server/mpm/worker/worker.c
-+++ httpd-2.2.4/server/mpm/worker/worker.c
-@@ -1813,12 +1813,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
-
- active_children = 0;
- for (index = 0; index < ap_daemons_limit; ++index) {
-- if (MPM_CHILD_PID(index) != 0) {
-- if (kill(MPM_CHILD_PID(index), 0) == 0) {
-- active_children = 1;
-- /* Having just one child is enough to stay around */
-- break;
-- }
-+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
-+ active_children = 1;
-+ /* Having just one child is enough to stay around */
-+ break;
- }
- }
- } while (!shutdown_pending && active_children &&
-Index: httpd-2.2.4/server/mpm/experimental/event/event.c
-===================================================================
---- httpd-2.2.4.orig/server/mpm/experimental/event/event.c
-+++ httpd-2.2.4/server/mpm/experimental/event/event.c
-@@ -1998,12 +1998,10 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_
-
- active_children = 0;
- for (index = 0; index < ap_daemons_limit; ++index) {
-- if (MPM_CHILD_PID(index) != 0) {
-- if (kill(MPM_CHILD_PID(index), 0) == 0) {
-- active_children = 1;
-- /* Having just one child is enough to stay around */
-- break;
-- }
-+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
-+ active_children = 1;
-+ /* Having just one child is enough to stay around */
-+ break;
- }
- }
- } while (!shutdown_pending && active_children &&
-Index: httpd-2.2.4/server/mpm_common.c
-===================================================================
---- httpd-2.2.4.orig/server/mpm_common.c
-+++ httpd-2.2.4/server/mpm_common.c
-@@ -126,6 +126,11 @@ static int reclaim_one_pid(pid_t pid, ac
- apr_proc_t proc;
- apr_status_t waitret;
-
-+ /* Ensure pid sanity. */
-+ if (pid < 1) {
-+ return 1;
-+ }
-+
- proc.pid = pid;
- waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT);
- if (waitret != APR_CHILD_NOTDONE) {
-@@ -305,6 +310,66 @@ void ap_relieve_child_processes(void)
- cur_extra = next;
- }
- }
-+
-+/* Before sending the signal to the pid this function verifies that
-+ * the pid is a member of the current process group; either using
-+ * apr_proc_wait(), where waitpid() guarantees to fail for non-child
-+ * processes; or by using getpgid() directly, if available. */
-+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
-+{
-+#ifndef HAVE_GETPGID
-+ apr_proc_t proc;
-+ apr_status_t rv;
-+ apr_exit_why_e why;
-+ int status;
-+
-+ /* Ensure pid sanity */
-+ if (pid < 1) {
-+ return APR_EINVAL;
-+ }
-+
-+ proc.pid = pid;
-+ rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT);
-+ if (rv == APR_CHILD_DONE) {
-+#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS
-+ /* The child already died - log the termination status if
-+ * necessary: */
-+ ap_process_child_status(&proc, why, status);
-+#endif
-+ return APR_EINVAL;
-+ }
-+ else if (rv != APR_CHILD_NOTDONE) {
-+ /* The child is already dead and reaped, or was a bogus pid -
-+ * log this either way. */
-+ ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf,
-+ "cannot send signal %d to pid %ld (non-child or "
-+ "already dead)", sig, (long)pid);
-+ return APR_EINVAL;
-+ }
-+#else
-+ pid_t pg;
-+
-+ /* Ensure pid sanity. */
-+ if (pid < 1) {
-+ return APR_EINVAL;
-+ }
-+
-+ pg = getpgid(pid);
-+ if (pg == -1) {
-+ /* Process already dead... */
-+ return errno;
-+ }
-+
-+ if (pg != getpgrp()) {
-+ ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf,
-+ "refusing to send signal %d to pid %ld outside "
-+ "process group", sig, (long)pid);
-+ return APR_EINVAL;
-+ }
-+#endif
-+
-+ return kill(pid, sig) ? errno : APR_SUCCESS;
-+}
- #endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */
-
- #ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT
-Index: httpd-2.2.4/include/mpm_common.h
-===================================================================
---- httpd-2.2.4.orig/include/mpm_common.h
-+++ httpd-2.2.4/include/mpm_common.h
-@@ -145,6 +145,19 @@ int ap_unregister_extra_mpm_process(pid_
- #endif
-
- /**
-+ * Safely signal an MPM child process, if the process is in the
-+ * current process group. Otherwise fail.
-+ * @param pid the process id of a child process to signal
-+ * @param sig the signal number to send
-+ * @return APR_SUCCESS if signal is sent, otherwise an error as per kill(3);
-+ * APR_EINVAL is returned if passed either an invalid (< 1) pid, or if
-+ * the pid is not in the current process group
-+ */
-+#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
-+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig);
-+#endif
-+
-+/**
- * Determine if any child process has died. If no child process died, then
- * this process sleeps for the amount of time specified by the MPM defined
- * macro SCOREBOARD_MAINTENANCE_INTERVAL.
-Index: httpd-2.2.4/include/ap_mmn.h
-===================================================================
---- httpd-2.2.4.orig/include/ap_mmn.h
-+++ httpd-2.2.4/include/ap_mmn.h
-@@ -113,6 +113,8 @@
- * 20051115.3 (2.2.3) Added server_scheme member to server_rec (minor)
- * 20051115.4 (2.2.4) Added ap_get_server_banner() and
- * ap_get_server_description() (minor)
-+ * 20051115.5 (2.2.5) Added ap_mpm_safe_kill() (minor)
-+ *
- */
-
- #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
-@@ -120,7 +122,7 @@
- #ifndef MODULE_MAGIC_NUMBER_MAJOR
- #define MODULE_MAGIC_NUMBER_MAJOR 20051115
- #endif
--#define MODULE_MAGIC_NUMBER_MINOR 4 /* 0...n */
-+#define MODULE_MAGIC_NUMBER_MINOR 5 /* 0...n */
-
- /**
- * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
-Index: httpd-2.2.4/configure.in
-===================================================================
---- httpd-2.2.4.orig/configure.in
-+++ httpd-2.2.4/configure.in
-@@ -392,6 +392,7 @@ initgroups \
- bindprocessor \
- prctl \
- timegm \
-+getpgid
- )
-
- dnl confirm that a void pointer is large enough to store a long integer
-Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c
-===================================================================
---- httpd-2.2.4.orig/server/mpm/experimental/itk/itk.c
-+++ httpd-2.2.4/server/mpm/experimental/itk/itk.c
-@@ -1199,7 +1199,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
- for (index = 0; index < ap_daemons_limit; ++index) {
- if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
- /* Ask each child to close its listeners. */
-- kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
-+ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
- active_children++;
- }
- }
-@@ -1237,12 +1237,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
-
- active_children = 0;
- for (index = 0; index < ap_daemons_limit; ++index) {
-- if (MPM_CHILD_PID(index) != 0) {
-- if (kill(MPM_CHILD_PID(index), 0) == 0) {
-- active_children = 1;
-- /* Having just one child is enough to stay around */
-- break;
-- }
-+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
-+ active_children = 1;
-+ /* Having just one child is enough to stay around */
-+ break;
- }
- }
- } while (!shutdown_pending && active_children &&
-@@ -1294,7 +1292,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p
- * piped loggers, etc. They almost certainly won't handle
- * it gracefully.
- */
-- kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
-+ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
- }
- }
- }