]> git.pld-linux.org Git - packages/apache.git/commitdiff
- EAPI support for apache.
authorkloczek <kloczek@pld-linux.org>
Wed, 29 Dec 1999 22:11:13 +0000 (22:11 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    apache-EAPI.patch -> 1.1

apache-EAPI.patch [new file with mode: 0644]

diff --git a/apache-EAPI.patch b/apache-EAPI.patch
new file mode 100644 (file)
index 0000000..0372cb3
--- /dev/null
@@ -0,0 +1,5540 @@
+diff -Nru apache_1.3.9/README.EAPI apache_1.3.9.EAPI/README.EAPI
+--- apache_1.3.9/README.EAPI   Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/README.EAPI      Wed Dec 29 21:25:55 1999
+@@ -0,0 +1,340 @@
++
++ Extended API (EAPI)
++ ===================
++
++ What is EAPI
++ ============
++
++ Extended API (EAPI) is a comprehensive API addition which can be _OPTIONALLY_
++ enabled with ``Rule EAPI=yes'' in src/Configuration or ``--enable-rule=EAPI''
++ on the APACI configure command line. This then defines a -DEAPI and this way
++ the EAPI code is compiled into Apache. When this define is not present _NO_
++ EAPI code is compiled into Apache at all, because all(!) EAPI patches are
++ encapsulated in #ifdef EAPI...#endif.
++
++ What is provided by EAPI?
++ =========================
++
++ EAPI's additions to the Apache API fall into the following categories:
++
++    o  Context Attachment Support for Data Structures
++    o  Loosly-coupled Hook Interface for Inter-Module Communication
++    o  Direct and Pool-based Shared Memory Support 
++    o  Additional Apache Module Hooks
++    o  Specialized EAPI Goodies
++
++ They are discussed in details now....
++
++ Context Attachment Support for Data Structures
++ ----------------------------------------------
++
++ Attaching private information to a request_rec, conn_rec, server_rec or even
++ BUFF structure is for a lot of modules the most elegant solution to keep
++ states between API phases without the need for any global variables. That's
++ especially true for modules which operate on lower I/O levels (where no
++ per-module configuration structure is available) or have to deal with various
++ callback functions of third-party libraries (where one need to find the
++ private context which can be hard without global variables).
++
++ The EAPI way to solve this situation is: 
++
++ 1. A generic context library was written which allows one
++    to create a context and later store and retrieve context variables
++    identified by a unique key.
++
++ 2. The Apache kernel was extended to provide contexts for all standard data
++    structures like request_rec, server_rec, conn_rec, BUFF, etc.  This way
++    modules can easily attach information to all these structures with the
++    help of the context API.
++
++ Point 1 is implemented by new src/ap/ap_ctx.c and src/include/ap_ctx.h source
++ files.  Point 2 is implemented by EAPI patches to various src/main/*.c and
++ src/include/*.h files.
++
++ Example:
++ 
++  | /* a module implements on-the-fly compression for
++  |    the buffer code and for this uses a third-party library which 
++  |    don't uses a filedescriptor. Instead a CLIB* is used.  The module has to
++  |    attach this CLIB* to the BUFF in oder to have it available whenever a
++  |    BUFF is used somewhere. */
++  | BUFF *buff;
++  | CLIB *comp;
++  | comp = CLIB_new_from_fd(buff->fd);
++  | ap_ctx_set(buff->ctx, "CLIB", comp);
++  |   :
++  | 
++  | /* later when it deals with a BUFF, it can easily find back the
++  |    CLIB* via the BUFF* */
++  | comp = (CLIB *)ap_ctx_get(buff->ctx, "CLIB");
++  |   :
++ 
++ Possible use cases from practice are:
++  
++  o  attaching third-party structures to Apache structures
++  o  replacing global module variables with clean context variables
++  o  custom attachments for complex modules like mod_php, mod_php, etc.
++  o  companion support for the hook interface (see below)
++  o  etc. pp.
++
++ Loosly-coupled Hook Interface for Inter-Module Communication
++ ------------------------------------------------------------
++
++ Apache is structured into modules which is a nice idea.  With the Dynamic
++ Shared Object (DSO) facility it gets even nicer because then modules are then
++ really stand-alone objects. The drawback is that DSO restricts modules.  The
++ most popular problem is that no inter-module symbol references are allowed.
++ The classical problem: Module A implements some nice functions module B would
++ like to use to avoid reimplementing the wheel. But B cannot call A's
++ functions because this violates both the design idea of stand-alone modules
++ and the DSO restrictions. Additionally a module C could exists which also
++ provides a variant of the functionality of A's function.  Then B should get
++ the variant (either A's or C's) which is best or available at all.
++ 
++ Real Life Example:
++
++ mod_rewrite provides %{XXXX} constructs to lookup variables.  The available
++ variables are (and have to be) hard-coded into mod_rewrite. Now our mod_clib
++ which does on-the-fly compression provides a variable CLIB_FACTOR which gives
++ information about the shrink factor of the compression and a user wants to
++ use this shrink factor to make an URL-rewriting decision (<grin>). No chance
++ without EAPI.  With EAPI it's easy: Inside the if-cascade for the various
++ variables in mod_rewrite one replaces:
++
++  | char *result;
++  | request_rec *r;
++  |    :
++  | if (strcasecmp(var, "...") == 0) {
++  |    :
++  | else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
++  |     result = ...
++  | }
++  | else {
++  |     if (result == NULL) {
++  |         ...complain...
++  |     }
++  | }
++  |    :
++
++ with
++
++  | char *result;
++  | request_rec *r;
++  |    :
++  | if (strcasecmp(var, "...") == 0) {
++  |    :
++  | else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
++  |     result = ...
++  | }
++  | else {
++  |     ap_hook_use("ap::lookup_variable",
++  |                 AP_HOOK_SIG4(ptr,ptr,ptr,ctx), 
++  |                 AP_HOOK_DECLINE(NULL),
++  |                 &result, r, var);
++  |     if (result == NULL) {
++  |         ...complain...
++  |     }
++  | }
++  |    :
++
++ What this does is that when XXXX of %{XXXX} isn't known, a hook named
++ ap::lookup_variable is called with the request_rec and the var ("XXX") and
++ the result variable. When no one has registered for this hook, nothing
++ happens. ap_hook_use() immediately returns and nothing was changed. 
++
++ But now let's assume mod_clib is additionally loaded as a DSO. And without
++ changing anything now magically mod_rewrite implements %{CLIB_FACTOR}. How?
++ Look inside mod_clib.c:
++
++  | /* mod_clib registeres for the ap::lookup_variable hook 
++  | inside it's init phase */
++  | CLIB *comp;
++  | ap_hook_register("ap::lookup_variable", 
++  |                  my_lookup_variable, AP_HOOK_CTX(comp));
++  |
++  | /* and implements the my_lookup_variable() function */
++  | char *my_lookup_variable(request_rec *r, char *name, CLIB *comp)
++  | {
++  |     if (strcmp(name, "CLIB_FACTOR") == 0)
++  |         return ap_psrintf(r->pool, "%d", comp->factor);
++  |     return NULL;
++  | }
++
++ What happens? When mod_rewrite calls the ap_hook_use() function internally
++ the hook facility knows that mod_clib has registered for this hook and calls
++ the equivalent of
++
++ |     result = my_lookup_variable(r, var, <comp>);
++
++ where <comp> is the CLIB* context variable mod_clib has registered for
++ itself. Now assume a second module exists which also provides variables and
++ want to allow mod_rewrite to lookup them.  It registers after mod_clib with
++
++ |      ap_hook_register("ap::lookup_variable", 
++ |                        my_lookup_variable2, AP_HOOK_CTX(whatever));
++ | 
++
++ and then the following happens: The hook facility does for mod_rewrite the
++ equivalent of:
++
++ |      result = my_lookup_variable(r, var, <comp>);
++ |      if (result == NULL)
++ |          result = my_lookup_variable2(r, var, <whatever>);
++
++ As you can see the hook functions decline in this example with NULL.  That's
++ the NULL from AP_HOOK_DECLINE(NULL) and can be any value of any type, of
++ course.
++
++ The same idea can be also used by mod_log_config and every other module which
++ wants to lookup a variable inside Apache. Which variables are available
++ depend on the available modules which implement them. And this all works
++ nicely with the DSO facility, because the ap_hook_xxx() API is part of the
++ Apache kernel code. And nothing has to be changed inside Apache when another
++ modules wants to create a new hook, because the mechanism is totally generic.
++
++ So when our module A wants to let other modules to use it's function it just
++ has to configure a hook for this.  Then other modules call this hook. Is
++ module A not there the boolean return value of the hook call will indicate
++ this. When module A is there the function is called.
++
++ Direct and Pool-based Shared Memory Support
++ -------------------------------------------
++
++ Since years it was annoying that Apache's pre-forked process model basically
++ means that every server lives it's own life (= address space) and this way
++ module authors cannot easily spread module configuration or other data
++ accross the processes.  The most elegant solution is to use shared memory
++ segments.  The drawback is that there is no portable API for shared memory
++ handling and there is no convinient memory allocation API for working inside
++ shared memory segments.
++
++ The EAPI way to solve this situation is: 
++
++ 1. A stand-alone and resuable library was written (named MM from "memory
++    mapped" and available from http://www.engelschall.com/sw/mm/) which
++    abstracts the shared memory and memory mutex fiddling into a low-level
++    API.  Internally the shared memory and mutex functionality is implemented
++    in various platform-depended ways: 4.4BSD or POSIX.1 anonymous memory
++    mapping, /dev/zero-based memory mapping, temporary file memory mapping, or
++    SysV IPC shared memory for allocating the shared memory areas and POSIX.1
++    fcntl(2), BSD flock(2) or SysV IPC semaphores for implementing mutual
++    exclusion capabilities.
++
++    Additionally MM provides a high-level malloc()-style API based on this
++    abstracted shared memory low-level API. The idea is just to allocate the
++    requested memory chunks from shared memory segments instead of the heap.
++
++ 2. EAPI now provides an easy method (with the EAPI_MM configuration 
++    variable) to build Apache against this MM library. For this the whole MM
++    API (mm_xxx() functions) is encapsulated in an Apache API subpart
++    (ap_mm_xxx() functions). This way the API is fixed and always present (no
++    #ifdef EAPI stuff in modules!), but useable only when EAPI was used in
++    conjunction with MM. A simple ``EAPI_MM=/path/to/mm ./configure
++    --enable-rule=EAPI ...'' is enough to put MM under the ap_mm_xxx() API.
++    This way modules can use a consistent, powerful and abstracted ap_mm_xxx()
++    API for dealing with shared memory.
++
++ 3. Because inside Apache mostly all memory handling is done via the
++    pool facility, additional support for ``shared memory pools'' is provided.
++    This way modules can use all ap_pxxx() functions in combination with
++    shared memory.
++
++ Point 1 is implemented inside the MM package. Point 2 is implemented by the
++ new src/ap/ap_mm.c and src/include/ap_mm.h source files.  Point 3 is
++ implemented by EAPI patches to src/main/alloc.c and src/include/alloc.h.
++
++ Example:
++
++ | /* inside a module init function (before the forking!)
++ |    for instance a module allocates a structure with a counter
++ |    in a shared memory segment */
++ | pool *p;
++ | pool *sp;
++ | struct mystuff { int cnt } *my;
++ | sp = ap_make_shared_sub_pool(p);
++ | my = (struct mystuff *)ap_palloc(sp, sizeof(struct mystuff));
++ | my->cnt = 0;
++ | 
++ |     :
++ | /* then under request processing time it's changed by one process */
++ | ap_acquire_pool(sp, AP_POOL_RW);
++ | my->cnt++;
++ | ap_release_pool(sp);
++ |     :
++ | 
++ | /* and at the same time read by other processes */
++ | ap_acquire_pool(sp, AP_POOL_RD);
++ | ap_rprintf(r, "The counter is %d\n", my->cnt);
++ | ap_release_pool(sp);
++
++ Possible use cases from practice are:
++
++  o  assembling traffic or other accounting details
++  o  establishing of high-performance inter-process caches
++  o  inter-process wide keeping of session state information
++  o  shared memory support for mod_perl, mod_php, etc.
++  o  etc. pp.
++
++ Additional Apache Module Hooks
++ ------------------------------
++
++ The above three EAPI additions are all very generic facilities.  But there
++ were also specialized things which were missing in Apache (and needed by
++ modules). Mostly additional API phases. EAPI adds the following additional
++ hook pointers to the module structure:
++
++ add_module: 
++     Called from within ap_add_module() right after the module structure
++     was linked into the Apache internal module list.  It is mainly
++     intended to be used to define configuration defines (<IfDefine>)
++     which have to be available directly after a LoadModule/AddModule.
++     Actually this is the earliest possible hook a module can use.  It's
++     especially important for the modules when they use the hook facility.
++
++ remove_module: 
++     Called from within ap_remove_module() right before the module
++     structure is kicked out from the Apache internal module list.
++     Actually this is last possible hook a module can use and exists for
++     consistency with the add_module hook.
++
++ rewrite_command:
++     Called right after a configuration directive line was read and
++     before it is processed. It is mainly intended to be used for
++     rewriting directives in order to provide backward compatibility to
++     old directive variants.
++
++ new_connection:
++     Called from within the internal new_connection() function, right
++     after the conn_rec structure for the new established connection was
++     created and before Apache starts processing the request with
++     ap_read_request().  It is mainly intended to be used to setup/run
++     connection dependent things like sending start headers for
++     on-the-fly compression, etc.
++
++ close_connection:
++     Called from within the Apache dispatching loop just before any
++     ap_bclose() is performed on the socket connection, but a long time
++     before any pool cleanups are done for the connection (which can be
++     too late for some applications).  It is mainly intended to be used
++     to close/finalize connection dependent things like sending end
++     headers for on-the-fly compression, etc.
++
++ Specialized EAPI Goodies
++ ------------------------
++
++ And finally EAPI now uses some of the new functionality to add a few new
++ EAPI-based goodies to mod_rewrite, mod_status and mod_proxy:
++
++ mod_rewrite:
++     The above presented example of lookup hooks is implemented which allows
++     mod_rewrite to lookup arbitrary variables provides by not known modules.
++
++ mod_status:
++     Any module now can register to an EAPI hook of mod_status which
++     allows it to put additional text on the /status webpages.
++
++ mod_proxy:  
++     Some EAPI hooks are provided to allow other modules to control the HTTP
++     client processing inside mod_proxy.  This can be used for a lot of
++     tricks.
++
+diff -Nru apache_1.3.9/htdocs/manual/mod/directives.html apache_1.3.9.EAPI/htdocs/manual/mod/directives.html
+--- apache_1.3.9/htdocs/manual/mod/directives.html     Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/htdocs/manual/mod/directives.html        Wed Dec 29 21:25:55 1999
+@@ -96,6 +96,7 @@
+ <LI><A HREF="mod_autoindex.html#defaulticon">DefaultIcon</A>
+ <LI><A HREF="mod_mime.html#defaultlanguage">DefaultLanguage</A>
+ <LI><A HREF="core.html#defaulttype">DefaultType</A>
++<LI><A HREF="mod_define.html#define">Define</A>
+ <LI><A HREF="mod_access.html#deny">deny</A>
+ <LI><A HREF="core.html#directory">&lt;Directory&gt;</A>
+ <LI><A HREF="core.html#directorymatch">&lt;DirectoryMatch&gt;</A>
+diff -Nru apache_1.3.9/htdocs/manual/mod/index.html apache_1.3.9.EAPI/htdocs/manual/mod/index.html
+--- apache_1.3.9/htdocs/manual/mod/index.html  Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/htdocs/manual/mod/index.html     Wed Dec 29 21:25:55 1999
+@@ -62,6 +62,8 @@
+ <DT><A HREF="mod_cookies.html">mod_cookies</A> up to Apache 1.1.1
+ <DD>Support for Netscape-like cookies.  Replaced in Apache 1.2 by
+ mod_usertrack
++<DT><A HREF="mod_define.html">mod_define</A>
++<DD>Variable Definition for Arbitrary Directives
+ <DT><A HREF="mod_digest.html">mod_digest</A>
+ <DD>MD5 authentication
+ <DT><A HREF="mod_dir.html">mod_dir</A>
+diff -Nru apache_1.3.9/htdocs/manual/mod/mod_define.html apache_1.3.9.EAPI/htdocs/manual/mod/mod_define.html
+--- apache_1.3.9/htdocs/manual/mod/mod_define.html     Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/htdocs/manual/mod/mod_define.html        Wed Dec 29 21:25:55 1999
+@@ -0,0 +1,135 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
++<!--%hypertext -->
++<!-- mod_define.html                                  -->
++<!-- Documentation for the mod_define Apache module   -->
++<HTML>
++<HEAD>
++<TITLE>Apache module mod_define</TITLE>
++</HEAD>
++
++<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
++<BODY
++ BGCOLOR="#FFFFFF"
++ TEXT="#000000"
++ LINK="#0000FF"
++ VLINK="#000080"
++ ALINK="#FF0000"
++>
++<BLOCKQUOTE><!-- page indentation -->
++<!--#include virtual="header.html" -->
++
++<BR>
++<H1 ALIGN="CENTER">Module mod_define</H1>
++<H2 ALIGN="CENTER">Variable Definition For Arbitrary Directives</H2>
++
++This module is contained in the <CODE>mod_define.c</CODE> file.  It provides
++the definition variables for arbitrary directives, i.e. variables which can be
++expanded on any(!) directive line. It needs Extended API (EAPI). It is not
++compiled into the server by default. To use <CODE>mod_define</CODE> you have
++to enable the following line in the server build <CODE>Configuration</CODE>
++file:
++
++<P>
++<PRE>
++    AddModule  modules/extra/mod_define.o
++</PRE>
++
++<P>
++<HR NOSHADE SIZE=1>
++
++<H3><A NAME="Define">Define</A></H3>
++<A
++ HREF="directive-dict.html#Syntax"
++ REL="Help"
++><STRONG>Syntax:</STRONG></A>
++    <CODE>Define</CODE> <EM>variable</EM> <EM>value</EM><BR>
++<A
++ HREF="directive-dict.html#Default"
++ REL="Help"
++><STRONG>Default:</STRONG></A>
++    <EM>none</EM><BR>
++<A
++ HREF="directive-dict.html#Context"
++ REL="Help"
++><STRONG>Context:</STRONG></A>
++    server config, virtual host, directory, .htaccess<BR>
++<A
++ HREF="directive-dict.html#Override"
++ REL="Help"
++><STRONG>Override:</STRONG></A> none<BR>
++<A
++ HREF="directive-dict.html#Status"
++ REL="Help"
++><STRONG>Status:</STRONG></A> Extension<BR>
++<A
++ HREF="directive-dict.html#Module"
++ REL="Help"
++><STRONG>Module:</STRONG></A> mod_define.c<BR>
++<A
++ HREF="directive-dict.html#Compatibility"
++ REL="Help"
++><STRONG>Compatibility:</STRONG></A> Apache+EAPI<BR>
++
++<P>
++The <CODE>Define</CODE> directive defines a variable which later can be
++expanded with the unsafe but short construct
++``<CODE>$</CODE><EM>variable</EM>'' or the safe but longer construct
++``<CODE>${</CODE><EM>variable</EM><CODE>}</CODE>'' on any configuration line.
++Do not intermix this with the third-party module <CODE>mod_macro</CODE>. The
++<CODE>mod_define</CODE> module doesn't provide a general macro mechanism,
++although one can consider variable substitutions as a special form of macros.
++Because the value of to which ``<CODE>$</CODE><EM>variable</EM>'' expands has
++to fit into one line. When you need macros which can span more lines, you've
++to use <CODE>mod_macro</CODE>. OTOH <CODE>mod_macro</CODE> cannot be used to
++expand a variable/macro on an arbitrary directive line.  So, the typical use
++case of <CODE>mod_define</CODE> is to make strings <EM>variable</EM> (and this
++way easily changeable at one location) and not to <EM>bundle</EM> things
++together (as it's the typical use case for macros).
++
++<P>
++The syntax of the expansion construct (
++``<CODE>${</CODE><EM>variable</EM><CODE>}</CODE>'') follows the Perl and Shell
++syntax, but can be changed via the <CODE>Define</CODE> directive, too. Four
++internal variables can be used for this. The default is:
++
++<BLOCKQUOTE>
++<PRE>
++Define mod_define::escape "\\"
++Define mod_define::dollar "$"
++Define mod_define::open   "{"
++Define mod_define::close  "}"
++</PRE>
++</BLOCKQUOTE>
++
++<P>
++When you need to escape some of the expansion constructs you place the
++mod_define::escape character in front of it.  The default is the backslash as
++in Perl or the Shell.
++
++<P>
++<STRONG>Example:</STRONG>
++<BLOCKQUOTE>
++<PRE>
++Define master     "Joe Average &lt;joe@average.dom&gt;"
++Define docroot    /usr/local/apache/htdocs
++Define hostname   foo
++Define domainname bar.dom
++Define portnumber 80
++  :
++&lt;VirtualHost $hostname.$domainname:$portnumber&gt;
++SetEnv       SERVER_MASTER "$master"
++ServerName   $hostname.$domainname
++ServerAlias  $hostname
++Port         $portnumber
++DocumentRoot $docroot
++&lt;Directory $docroot&gt;
++  :
++&lt;Directory&gt;
++</PRE>
++</BLOCKQUOTE>
++
++<!--#include virtual="footer.html" -->
++</BLOCKQUOTE><!-- page indentation -->
++</BODY>
++</HTML>
++<!--/%hypertext -->
+diff -Nru apache_1.3.9/src/ApacheCore.def apache_1.3.9.EAPI/src/ApacheCore.def
+--- apache_1.3.9/src/ApacheCore.def    Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/ApacheCore.def       Wed Dec 29 21:25:55 1999
+@@ -359,4 +359,17 @@
+       ap_SHA1Update   @354
+       ap_SHA1Final   @355
+       ap_sha1_base64   @356
++      ap_add_config_define   @357
++      ap_global_ctx   @358
++      ap_ctx_new   @359
++      ap_ctx_get   @360
++      ap_ctx_set   @361
++      ap_hook_init   @362
++      ap_hook_kill   @363
++      ap_hook_configure   @364
++      ap_hook_register_I   @365
++      ap_hook_unregister_I   @366
++      ap_hook_status   @367
++      ap_hook_use   @368
++      ap_hook_call   @369
+diff -Nru apache_1.3.9/src/Configuration.tmpl apache_1.3.9.EAPI/src/Configuration.tmpl
+--- apache_1.3.9/src/Configuration.tmpl        Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/Configuration.tmpl   Wed Dec 29 21:27:21 1999
+@@ -68,6 +68,24 @@
+ #TARGET=
+ ################################################################
++# Extended API (EAPI) support:
++#
++# EAPI:
++#   The EAPI rule enables more module hooks, a generic low-level hook
++#   mechanism, a generic context mechanism and shared memory based pools. 
++#
++# EAPI_MM:
++#   Set the EAPI_MM variable to either the directory of a MM Shared Memory
++#   Library source tree or the installation tree of MM. Alternatively you can
++#   also use the value 'SYSTEM' which then indicates that MM is installed
++#   under various system locations. When the MM library files cannot be found
++#   the EAPI still can be built, but without shared memory pool support, of
++#   course.
++
++Rule EAPI=no
++EAPI_MM=SYSTEM
++
++################################################################
+ # Dynamic Shared Object (DSO) support
+ #
+ # There is experimental support for compiling the Apache core and
+@@ -246,6 +265,11 @@
+ ## it does not do per-request stuff.
+ AddModule modules/standard/mod_env.o
++
++## mod_define expands variables on arbitrary directive lines.
++## It requires Extended API (EAPI).
++
++# AddModule modules/extra/mod_define.o
+ ##
+ ## Request logging modules
+diff -Nru apache_1.3.9/src/Configure apache_1.3.9.EAPI/src/Configure
+--- apache_1.3.9/src/Configure Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/Configure    Wed Dec 29 21:42:17 1999
+@@ -1725,6 +1732,72 @@
+     SUBDIRS="regex $SUBDIRS"
+     CFLAGS="$CFLAGS -DUSE_HSREGEX"
+ fi
++
++####################################################################
++## Extended API (EAPI) support:
++##
++if [ "x$RULE_EAPI" = "x" ]; then
++    RULE_EAPI=`./helpers/CutRule EAPI $file`
++fi
++if [ "x$RULE_EAPI" = "xyes" ]; then
++    echo " + enabling Extended API (EAPI)"
++    CFLAGS="$CFLAGS -DEAPI"
++    #   some vendor compilers are too restrictive
++    #   for our ap_hook and ap_ctx sources.
++    case "$OS:$CC" in
++        *IRIX-32*:*/cc|*IRIX-32*:cc )
++            CFLAGS="$CFLAGS -woff 1048,1110,1164"
++            ;;
++    esac
++    #   MM Shared Memory Library support for EAPI
++    if [ "x$EAPI_MM" = "x" ]; then
++        EAPI_MM=`egrep '^EAPI_MM=' $file | tail -1 | awk -F= '{print $2}'`
++    fi
++    if [ "x$EAPI_MM" != "x" ]; then
++        case $EAPI_MM in
++            SYSTEM|/* ) ;;
++            * ) for p in . .. ../..; do
++                    if [ -d "$p/$EAPI_MM" ]; then
++                        EAPI_MM="`echo $p/$EAPI_MM | sed -e 's;/\./;/;g'`" 
++                        break
++                    fi
++                done
++                ;;
++        esac
++        if [ "x$EAPI_MM" = "xSYSTEM" ]; then
++            echo "   using MM library for EAPI: (system-wide)"
++            CFLAGS="$CFLAGS -DEAPI_MM"
++            __INCLUDES="`mm-config --cflags`"
++            if [ "x$__INCLUDES" != "x-I/usr/include" ]; then
++                INCLUDES="$INCLUDES $__INCLUDES"
++            fi
++            LDFLAGS="$LDFLAGS `mm-config --ldflags`"
++            LIBS="$LIBS `mm-config --libs`"
++        else
++            if [ -f "$EAPI_MM/.libs/libmm.a" -a -f "$EAPI_MM/mm.h" ]; then
++                echo "   using MM library: $EAPI_MM (source-tree only)"
++                case $EAPI_MM in
++                    /* ) ;;
++                    *  ) EAPI_MM="\$(SRCDIR)/$EAPI_MM" ;;
++                esac
++                CFLAGS="$CFLAGS -DEAPI_MM"
++                INCLUDES="$INCLUDES -I$EAPI_MM"
++                LDFLAGS="$LDFLAGS -L$EAPI_MM/.libs"
++                LIBS="$LIBS -lmm"
++            elif [ -f "$EAPI_MM/bin/mm-config" ]; then
++                echo "   using MM library: $EAPI_MM (installed)"
++                CFLAGS="$CFLAGS -DEAPI_MM"
++                INCLUDES="$INCLUDES `$EAPI_MM/bin/mm-config --cflags`"
++                LDFLAGS="$LDFLAGS `$EAPI_MM/bin/mm-config --ldflags`"
++                LIBS="$LIBS `$EAPI_MM/bin/mm-config --libs`"
++            else
++                echo "Configure:Error: Cannot find MM library under $EAPI_MM" 1>&2
++                exit 1
++            fi
++        fi
++    fi
++fi
++
+ ####################################################################
+ ## Add in the Expat library if needed/wanted.
+diff -Nru apache_1.3.9/src/ap/Makefile.tmpl apache_1.3.9.EAPI/src/ap/Makefile.tmpl
+--- apache_1.3.9/src/ap/Makefile.tmpl  Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/ap/Makefile.tmpl     Wed Dec 29 21:25:56 1999
+@@ -6,7 +6,8 @@
+ LIB=libap.a
+ OBJS=ap_cpystrn.o ap_execve.o ap_fnmatch.o ap_getpass.o ap_md5c.o ap_signal.o \
+-     ap_slack.o ap_snprintf.o ap_sha1.o ap_checkpass.o ap_base64.o
++     ap_slack.o ap_snprintf.o ap_sha1.o ap_checkpass.o ap_base64.o \
++     ap_hook.o ap_ctx.o ap_mm.o
+ .c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $<
+diff -Nru apache_1.3.9/src/ap/ap.mak apache_1.3.9.EAPI/src/ap/ap.mak
+--- apache_1.3.9/src/ap/ap.mak Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/ap/ap.mak    Wed Dec 29 21:25:56 1999
+@@ -47,6 +47,9 @@
+       -@erase "$(INTDIR)\ap_cpystrn.obj"
+       -@erase "$(INTDIR)\ap_fnmatch.obj"
+       -@erase "$(INTDIR)\ap_md5c.obj"
++      -@erase "$(INTDIR)\ap_hook.obj"
++      -@erase "$(INTDIR)\ap_ctx.obj"
++      -@erase "$(INTDIR)\ap_mm.obj"
+       -@erase "$(INTDIR)\ap_signal.obj"
+       -@erase "$(INTDIR)\ap_slack.obj"
+       -@erase "$(INTDIR)\ap_snprintf.obj"
+@@ -105,6 +108,9 @@
+       "$(INTDIR)\ap_cpystrn.obj" \
+       "$(INTDIR)\ap_fnmatch.obj" \
+       "$(INTDIR)\ap_md5c.obj" \
++      "$(INTDIR)\ap_hook.obj" \
++      "$(INTDIR)\ap_ctx.obj" \
++      "$(INTDIR)\ap_mm.obj" \
+       "$(INTDIR)\ap_signal.obj" \
+       "$(INTDIR)\ap_slack.obj" \
+       "$(INTDIR)\ap_snprintf.obj" \
+@@ -139,6 +145,9 @@
+       -@erase "$(INTDIR)\ap_cpystrn.obj"
+       -@erase "$(INTDIR)\ap_fnmatch.obj"
+       -@erase "$(INTDIR)\ap_md5c.obj"
++      -@erase "$(INTDIR)\ap_hook.obj"
++      -@erase "$(INTDIR)\ap_ctx.obj"
++      -@erase "$(INTDIR)\ap_mm.obj"
+       -@erase "$(INTDIR)\ap_signal.obj"
+       -@erase "$(INTDIR)\ap_slack.obj"
+       -@erase "$(INTDIR)\ap_snprintf.obj"
+@@ -197,6 +206,9 @@
+       "$(INTDIR)\ap_cpystrn.obj" \
+       "$(INTDIR)\ap_fnmatch.obj" \
+       "$(INTDIR)\ap_md5c.obj" \
++      "$(INTDIR)\ap_hook.obj" \
++      "$(INTDIR)\ap_ctx.obj" \
++      "$(INTDIR)\ap_mm.obj" \
+       "$(INTDIR)\ap_signal.obj" \
+       "$(INTDIR)\ap_slack.obj" \
+       "$(INTDIR)\ap_snprintf.obj" \
+diff -Nru apache_1.3.9/src/ap/ap_ctx.c apache_1.3.9.EAPI/src/ap/ap_ctx.c
+--- apache_1.3.9/src/ap/ap_ctx.c       Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/ap/ap_ctx.c  Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,155 @@
++/* ====================================================================
++ * Copyright (c) 1998 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ *
++ */
++
++/*
++**  Generic Context Interface for Apache
++**  Written by Ralf S. Engelschall <rse@engelschall.com> 
++*/
++
++#ifdef EAPI
++
++#include "httpd.h"
++#include "ap_config.h"
++#include "ap_ctx.h"
++
++API_EXPORT(ap_ctx *) ap_ctx_new(pool *p)
++{
++    ap_ctx *ctx;
++    int i;
++
++    if (p != NULL) {
++        ctx = (ap_ctx *)ap_palloc(p, sizeof(ap_ctx_rec));
++        ctx->cr_pool = p;
++        ctx->cr_entry = (ap_ctx_entry **)
++            ap_palloc(p, sizeof(ap_ctx_entry *)*(AP_CTX_MAX_ENTRIES+1));
++    }
++    else {
++        ctx = (ap_ctx *)malloc(sizeof(ap_ctx_rec));
++        ctx->cr_pool = NULL;
++        ctx->cr_entry = (ap_ctx_entry **)
++            malloc(sizeof(ap_ctx_entry *)*(AP_CTX_MAX_ENTRIES+1));
++    }
++    for (i = 0; i < AP_CTX_MAX_ENTRIES+1; i++) 
++        ctx->cr_entry[i] = NULL;
++    return ctx;
++}
++
++API_EXPORT(void) ap_ctx_set(ap_ctx *ctx, char *key, void *val)
++{
++    int i;
++    ap_ctx_entry *ce;
++
++    ce = NULL;
++    for (i = 0; ctx->cr_entry[i] != NULL; i++) {
++        if (strcmp(ctx->cr_entry[i]->ce_key, key) == 0) {
++            ce = ctx->cr_entry[i];
++            break;
++        }
++    }
++    if (ce == NULL) {
++        if (i == AP_CTX_MAX_ENTRIES)
++            return;
++        if (ctx->cr_pool != NULL) {
++            ce = (ap_ctx_entry *)ap_palloc(ctx->cr_pool, sizeof(ap_ctx_entry));
++            ce->ce_key = ap_pstrdup(ctx->cr_pool, key);
++        }
++        else {
++            ce = (ap_ctx_entry *)malloc(sizeof(ap_ctx_entry));
++            ce->ce_key = strdup(key);
++        }
++        ctx->cr_entry[i] = ce;
++        ctx->cr_entry[i+1] = NULL;
++    }
++    ce->ce_val = val;
++    return;
++}
++
++API_EXPORT(void *) ap_ctx_get(ap_ctx *ctx, char *key)
++{
++    int i;
++
++    for (i = 0; ctx->cr_entry[i] != NULL; i++)
++        if (strcmp(ctx->cr_entry[i]->ce_key, key) == 0)
++            return ctx->cr_entry[i]->ce_val;
++    return NULL;
++}
++
++API_EXPORT(ap_ctx *) ap_ctx_overlay(pool *p, ap_ctx *over, ap_ctx *base)
++{
++    ap_ctx *new;
++    int i;
++
++#ifdef POOL_DEBUG
++    if (p != NULL) {
++        if (!ap_pool_is_ancestor(over->cr_pool, p))
++            ap_log_assert("ap_ctx_overlay: overlay's pool is not an ancestor of p", 
++                          __FILE__, __LINE__);
++        if (!ap_pool_is_ancestor(base->cr_pool, p))
++            ap_log_assert("ap_ctx_overlay: base's pool is not an ancestor of p",
++                          __FILE__, __LINE__);
++    }
++#endif
++    if ((new = ap_ctx_new(p)) == NULL)
++        return NULL;
++    memcpy(new->cr_entry, base->cr_entry, 
++           sizeof(ap_ctx_entry *)*(AP_CTX_MAX_ENTRIES+1));
++    for (i = 0; over->cr_entry[i] != NULL; i++)
++        ap_ctx_set(new, over->cr_entry[i]->ce_key, over->cr_entry[i]->ce_val);
++    return new;
++}
++
++#endif /* EAPI */
+diff -Nru apache_1.3.9/src/ap/ap_hook.c apache_1.3.9.EAPI/src/ap/ap_hook.c
+--- apache_1.3.9/src/ap/ap_hook.c      Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/ap/ap_hook.c Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,930 @@
++#if 0
++=pod
++#endif
++/* ====================================================================
++ * Copyright (c) 1998 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ *
++ */
++
++/*
++**  Implementation of a Generic Hook Interface for Apache
++**  Written by Ralf S. Engelschall <rse@engelschall.com> 
++**
++**  See POD document at end of ap_hook.h for description.
++**  View it with the command ``pod2man ap_hook.h | nroff -man | more''
++**
++**  Attention: This source file is a little bit tricky.
++**             It's a combination of a C source and an embedded Perl script
++**             (which updates the C source). The purpose of this is to have
++**             both things together at one place. So you can both pass
++**             this file to the C compiler and the Perl interpreter.
++*/
++
++                                      /*
++                                       * Premature optimization is 
++                                       * the root of all evil.
++                                       *       -- D. E. Knuth
++                                       */
++
++#ifdef EAPI
++
++#include "httpd.h"
++#include "http_log.h"
++#include "ap_config.h"
++#include "ap_hook.h"
++
++/* 
++ * the internal hook pool
++ */
++static ap_hook_entry **ap_hook_pool = NULL;
++
++/* 
++ * forward prototypes for internal functions
++ */
++static int            ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf);
++static ap_hook_entry *ap_hook_create(char *hook);
++static ap_hook_entry *ap_hook_find(char *hook);
++static void           ap_hook_destroy(ap_hook_entry *he);
++
++/*
++ * Initialize the hook mechanism
++ */
++API_EXPORT(void) ap_hook_init(void)
++{
++    int i;
++
++    if (ap_hook_pool != NULL)
++        return;
++    ap_hook_pool = (ap_hook_entry **)malloc(sizeof(ap_hook_entry *)
++                                            *(AP_HOOK_MAX_ENTRIES+1));
++    for (i = 0; i < AP_HOOK_MAX_ENTRIES; i++)
++        ap_hook_pool[i] = NULL;
++    return;
++}
++
++/*
++ * Kill the hook mechanism
++ */
++API_EXPORT(void) ap_hook_kill(void)
++{
++    int i;
++
++    if (ap_hook_pool == NULL)
++        return;
++    for (i = 0; ap_hook_pool[i] != NULL; i++)
++        ap_hook_destroy(ap_hook_pool[i]);
++    free(ap_hook_pool);
++    ap_hook_pool = NULL;
++    return;
++}
++    
++/*
++ * Smart creation of a hook (when it exist this is the same as
++ * ap_hook_find, when it doesn't exists it is created)
++ */
++static ap_hook_entry *ap_hook_create(char *hook)
++{
++    int i;
++    ap_hook_entry *he;
++
++    for (i = 0; ap_hook_pool[i] != NULL; i++)
++        if (strcmp(ap_hook_pool[i]->he_hook, hook) == 0)
++            return ap_hook_pool[i];
++
++    if (i >= AP_HOOK_MAX_ENTRIES)
++        return NULL;
++
++    if ((he = (ap_hook_entry *)malloc(sizeof(ap_hook_entry))) == NULL)
++        return NULL;
++    ap_hook_pool[i] = he;
++
++    he->he_hook          = strdup(hook);
++    he->he_sig           = AP_HOOK_SIG_UNKNOWN;
++    he->he_modeid        = AP_HOOK_MODE_UNKNOWN;
++    he->he_modeval.v_int = 0;
++
++    he->he_func = (ap_hook_func **)malloc(sizeof(ap_hook_func *)
++                                          *(AP_HOOK_MAX_FUNCS+1));
++    if (he->he_func == NULL)
++        return FALSE;
++
++    for (i = 0; i < AP_HOOK_MAX_FUNCS; i++)
++        he->he_func[i] = NULL;
++    return he;
++}
++
++/*
++ * Find a particular hook
++ */
++static ap_hook_entry *ap_hook_find(char *hook)
++{
++    int i;
++
++    for (i = 0; ap_hook_pool[i] != NULL; i++)
++        if (strcmp(ap_hook_pool[i]->he_hook, hook) == 0)
++            return ap_hook_pool[i];
++    return NULL;
++}
++
++/*
++ * Destroy a particular hook
++ */
++static void ap_hook_destroy(ap_hook_entry *he)
++{
++    int i;
++
++    if (he == NULL)
++        return;
++    free(he->he_hook);
++    for (i = 0; he->he_func[i] != NULL; i++)
++        free(he->he_func[i]);
++    free(he->he_func);
++    free(he);
++    return;
++}
++
++/*
++ * Configure a particular hook, 
++ * i.e. remember its signature and return value mode
++ */
++API_EXPORT(int) ap_hook_configure(char *hook, ap_hook_sig sig, ap_hook_mode modeid, ...)
++{
++    ap_hook_entry *he;
++    va_list ap;
++    int rc;
++
++    va_start(ap, modeid);
++    if ((he = ap_hook_create(hook)) == NULL)
++        rc = FALSE;
++    else {
++        he->he_sig = sig;
++        he->he_modeid = modeid;
++        if (modeid == AP_HOOK_MODE_DECLINE || modeid == AP_HOOK_MODE_DECLTMP) {
++            if (AP_HOOK_SIG_HAS(sig, RC, char))
++                he->he_modeval.v_char = va_arg(ap, va_type(char));
++            else if (AP_HOOK_SIG_HAS(sig, RC, int))
++                he->he_modeval.v_int = va_arg(ap, va_type(int));
++            else if (AP_HOOK_SIG_HAS(sig, RC, long))
++                he->he_modeval.v_long = va_arg(ap, va_type(long));
++            else if (AP_HOOK_SIG_HAS(sig, RC, float))
++                he->he_modeval.v_float = va_arg(ap, va_type(float));
++            else if (AP_HOOK_SIG_HAS(sig, RC, double))
++                he->he_modeval.v_double = va_arg(ap, va_type(double));
++            else if (AP_HOOK_SIG_HAS(sig, RC, ptr))
++                he->he_modeval.v_ptr = va_arg(ap, va_type(ptr));
++        }
++        rc = TRUE;
++    }
++    va_end(ap);
++    return rc;
++}
++
++/*
++ * Register a function to call for a hook
++ */
++API_EXPORT(int) ap_hook_register_I(char *hook, void *func, void *ctx)
++{
++    int i, j;
++    ap_hook_entry *he;
++    ap_hook_func *hf;
++
++    if ((he = ap_hook_create(hook)) == NULL)
++        return FALSE;
++
++    for (i = 0; he->he_func[i] != NULL; i++)
++        if (he->he_func[i]->hf_ptr == func)
++            return FALSE;
++
++    if (i == AP_HOOK_MAX_FUNCS)
++        return FALSE;
++
++    if ((hf = (ap_hook_func *)malloc(sizeof(ap_hook_func))) == NULL)
++        return FALSE;
++
++    for (j = i; j >= 0; j--)
++        he->he_func[j+1] = he->he_func[j];
++    he->he_func[0] = hf;
++
++    hf->hf_ptr = func;
++    hf->hf_ctx = ctx;
++
++    return TRUE;
++}
++
++/*
++ * Unregister a function to call for a hook
++ */
++API_EXPORT(int) ap_hook_unregister_I(char *hook, void *func)
++{
++    int i, j;
++    ap_hook_entry *he;
++
++    if ((he = ap_hook_find(hook)) == NULL)
++        return FALSE;
++    for (i = 0; he->he_func[i] != NULL; i++) {
++        if (he->he_func[i]->hf_ptr == func) {
++            free(he->he_func[i]);
++            for (j = i; he->he_func[j] != NULL; j++)
++                he->he_func[j] = he->he_func[j+1];
++            return TRUE;
++        }
++    }
++    return FALSE;
++}
++
++/*
++ * Retrieve the status of a particular hook
++ */
++API_EXPORT(ap_hook_state) ap_hook_status(char *hook)
++{
++    ap_hook_entry *he;
++
++    if ((he = ap_hook_find(hook)) == NULL)
++        return AP_HOOK_STATE_NOTEXISTANT;
++    if (   he->he_func[0] != NULL 
++        && he->he_sig != AP_HOOK_SIG_UNKNOWN
++        && he->he_modeid != AP_HOOK_MODE_UNKNOWN)
++        return AP_HOOK_STATE_REGISTERED;
++    if (   he->he_sig != AP_HOOK_SIG_UNKNOWN 
++        && he->he_modeid != AP_HOOK_MODE_UNKNOWN)
++        return AP_HOOK_STATE_CONFIGURED;
++    return AP_HOOK_STATE_ESTABLISHED;
++}
++
++/*
++ * Use a hook, i.e. optional on-the-fly configure it before calling it
++ */
++API_EXPORT(int) ap_hook_use(char *hook, ap_hook_sig sig, ap_hook_mode modeid, ...)
++{
++    int i;
++    ap_hook_value modeval;
++    ap_hook_entry *he;
++    va_list ap;
++    int rc;
++
++    va_start(ap, modeid);
++
++    if (modeid == AP_HOOK_MODE_DECLINE || modeid == AP_HOOK_MODE_DECLTMP) {
++        if (AP_HOOK_SIG_HAS(sig, RC, char))
++            modeval.v_char = va_arg(ap, va_type(char));
++        else if (AP_HOOK_SIG_HAS(sig, RC, int))
++            modeval.v_int = va_arg(ap, va_type(int));
++        else if (AP_HOOK_SIG_HAS(sig, RC, long))
++            modeval.v_long = va_arg(ap, va_type(long));
++        else if (AP_HOOK_SIG_HAS(sig, RC, float))
++            modeval.v_float = va_arg(ap, va_type(float));
++        else if (AP_HOOK_SIG_HAS(sig, RC, double))
++            modeval.v_double = va_arg(ap, va_type(double));
++        else if (AP_HOOK_SIG_HAS(sig, RC, ptr))
++            modeval.v_ptr = va_arg(ap, va_type(ptr));
++    }
++
++    if ((he = ap_hook_create(hook)) == NULL)
++        return FALSE;
++
++    if (he->he_sig == AP_HOOK_SIG_UNKNOWN)
++        he->he_sig = sig;
++    if (he->he_modeid == AP_HOOK_MODE_UNKNOWN) {
++        he->he_modeid  = modeid;
++        he->he_modeval = modeval;
++    }
++
++    for (i = 0; he->he_func[i] != NULL; i++)
++        if (ap_hook_call_func(ap, he, he->he_func[i]))
++            break;
++
++    if (i > 0 && he->he_modeid == AP_HOOK_MODE_ALL)
++        rc = TRUE;
++    else if (i == AP_HOOK_MAX_FUNCS || he->he_func[i] == NULL)
++        rc = FALSE;
++    else
++        rc = TRUE;
++
++    va_end(ap);
++    return rc;
++}
++
++/*
++ * Call a hook
++ */
++API_EXPORT(int) ap_hook_call(char *hook, ...)
++{
++    int i;
++    ap_hook_entry *he;
++    va_list ap;
++    int rc;
++    
++    va_start(ap, hook);
++
++    if ((he = ap_hook_find(hook)) == NULL) {
++        va_end(ap);
++        return FALSE;
++    }
++    if (   he->he_sig == AP_HOOK_SIG_UNKNOWN
++        || he->he_modeid == AP_HOOK_MODE_UNKNOWN) {
++        va_end(ap);
++        return FALSE;
++    }
++
++    for (i = 0; he->he_func[i] != NULL; i++)
++        if (ap_hook_call_func(ap, he, he->he_func[i]))
++            break;
++
++    if (i > 0 && he->he_modeid == AP_HOOK_MODE_ALL)
++        rc = TRUE;
++    else if (i == AP_HOOK_MAX_FUNCS || he->he_func[i] == NULL)
++        rc = FALSE;
++    else
++        rc = TRUE;
++
++    va_end(ap);
++    return rc;
++}
++
++static int ap_hook_call_func(va_list ap, ap_hook_entry *he, ap_hook_func *hf)
++{
++    void *v_rc;
++    ap_hook_value v_tmp;
++    int rc;
++
++    /*
++     * Now we dispatch the various function calls. We support function
++     * signatures with up to 9 types (1 return type, 8 argument types) where
++     * each argument can have 7 different types (ctx, char, int, long, float,
++     * double, ptr), so theoretically there are 9^7 (=4782969) combinations
++     * possible.  But because we don't need all of them, of course, we
++     * implement only the following well chosen subset (duplicates are ok):
++     *
++     * 1. `The basic hook'.
++     *
++     *    void func()
++     *
++     * 2. The standard set of signatures which form all combinations of
++     *    int&ptr based signatures for up to 3 arguments. We provide
++     *    them per default for module authors.
++     *
++     *    int func()
++     *    ptr func()
++     *    int func(int)
++     *    int func(ptr)
++     *    ptr func(int)
++     *    ptr func(ptr)
++     *    int func(int,int)
++     *    int func(int,ptr)
++     *    int func(ptr,int)
++     *    int func(ptr,ptr)
++     *    ptr func(int,int)
++     *    ptr func(int,ptr)
++     *    ptr func(ptr,int)
++     *    ptr func(ptr,ptr)
++     *    int func(int,int,int)
++     *    int func(int,int,ptr)
++     *    int func(int,ptr,int)
++     *    int func(int,ptr,ptr)
++     *    int func(ptr,int,int)
++     *    int func(ptr,int,ptr)
++     *    int func(ptr,ptr,int)
++     *    int func(ptr,ptr,ptr)
++     *    ptr func(int,int,int)
++     *    ptr func(int,int,ptr)
++     *    ptr func(int,ptr,int)
++     *    ptr func(int,ptr,ptr)
++     *    ptr func(ptr,int,int)
++     *    ptr func(ptr,int,ptr)
++     *    ptr func(ptr,ptr,int)
++     *    ptr func(ptr,ptr,ptr)
++     *
++     * 3. Actually currently used hooks.
++     *
++     *    int   func(ptr)                          [2x]
++     *    int   func(ptr,ptr)                      [2x]
++     *    int   func(ptr,ptr,int)                  [5x]
++     *    int   func(ptr,ptr,ptr,int)              [1x]
++     *    int   func(ptr,ptr,ptr,int,ptr)          [1x]
++     *    int   func(ptr,ptr,ptr,ptr,int)          [1x]
++     *    int   func(ptr,ptr,ptr,ptr,int,ptr)      [1x]
++     *    ptr   func(ptr,ptr)                      [3x]
++     *    ptr   func(ptr,ptr,ptr,ptr,ptr)          [1x]
++     *    void  func(ptr)                          [2x]
++     *    void  func(ptr,int,int)                  [1x]
++     *    void  func(ptr,ptr)                      [5x]
++     *    void  func(ptr,ptr,ptr)                  [3x]
++     *    void  func(ptr,ptr,ptr,ptr)              [2x]
++     *
++     * To simplify the programming task we generate the actual dispatch code
++     * for these calls via the embedded Perl script at the end of this source
++     * file. This script parses the above lines and generates the section
++     * below.  So, when you need more signature variants just add them to the
++     * above list and run
++     *
++     *     $ perl ap_hook.c
++     *
++     * This automatically updates the above code.
++     */
++
++    rc = TRUE;
++    v_rc = NULL;
++    if (!AP_HOOK_SIG_HAS(he->he_sig, RC, void)) {
++        if (he->he_modeid == AP_HOOK_MODE_DECLTMP) {
++            /* the return variable is a temporary one */ 
++            if (AP_HOOK_SIG_HAS(he->he_sig, RC, char))
++                v_rc = &v_tmp.v_char;
++            else if (AP_HOOK_SIG_HAS(he->he_sig, RC, int))
++                v_rc = &v_tmp.v_int;
++            else if (AP_HOOK_SIG_HAS(he->he_sig, RC, long))
++                v_rc = &v_tmp.v_long;
++            else if (AP_HOOK_SIG_HAS(he->he_sig, RC, float))
++                v_rc = &v_tmp.v_float;
++            else if (AP_HOOK_SIG_HAS(he->he_sig, RC, double))
++                v_rc = &v_tmp.v_double;
++            else if (AP_HOOK_SIG_HAS(he->he_sig, RC, ptr))
++                v_rc = &v_tmp.v_ptr;
++        }
++        else {
++            /* the return variable is provided by caller */ 
++            v_rc = va_arg(ap, void *);
++        }
++    }
++
++    /* ----BEGIN GENERATED SECTION-------- */
++    if (he->he_sig == AP_HOOK_SIG1(void)) {
++        /* Call: void func() */
++        ((void(*)())(hf->hf_ptr))();
++    }
++    else if (he->he_sig == AP_HOOK_SIG1(int)) {
++        /* Call: int func() */
++        *((int *)v_rc) = ((int(*)())(hf->hf_ptr))();
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG1(ptr)) {
++        /* Call: ptr func() */
++        *((void * *)v_rc) = ((void *(*)())(hf->hf_ptr))();
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG2(int, int)) {
++        /* Call: int func(int) */
++        int   v1 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(int))(hf->hf_ptr))(v1);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG2(int, ptr)) {
++        /* Call: int func(ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(void *))(hf->hf_ptr))(v1);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG2(ptr, int)) {
++        /* Call: ptr func(int) */
++        int   v1 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(int))(hf->hf_ptr))(v1);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG2(ptr, ptr)) {
++        /* Call: ptr func(ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(void *))(hf->hf_ptr))(v1);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(int, int, int)) {
++        /* Call: int func(int,int) */
++        int   v1 = va_arg(ap, va_type(int));
++        int   v2 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(int, int))(hf->hf_ptr))(v1, v2);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(int, int, ptr)) {
++        /* Call: int func(int,ptr) */
++        int   v1 = va_arg(ap, va_type(int));
++        void *v2 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(int, void *))(hf->hf_ptr))(v1, v2);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(int, ptr, int)) {
++        /* Call: int func(ptr,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(void *, int))(hf->hf_ptr))(v1, v2);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(int, ptr, ptr)) {
++        /* Call: int func(ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(void *, void *))(hf->hf_ptr))(v1, v2);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(ptr, int, int)) {
++        /* Call: ptr func(int,int) */
++        int   v1 = va_arg(ap, va_type(int));
++        int   v2 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(int, int))(hf->hf_ptr))(v1, v2);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(ptr, int, ptr)) {
++        /* Call: ptr func(int,ptr) */
++        int   v1 = va_arg(ap, va_type(int));
++        void *v2 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(int, void *))(hf->hf_ptr))(v1, v2);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(ptr, ptr, int)) {
++        /* Call: ptr func(ptr,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(void *, int))(hf->hf_ptr))(v1, v2);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(ptr, ptr, ptr)) {
++        /* Call: ptr func(ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(void *, void *))(hf->hf_ptr))(v1, v2);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, int, int, int)) {
++        /* Call: int func(int,int,int) */
++        int   v1 = va_arg(ap, va_type(int));
++        int   v2 = va_arg(ap, va_type(int));
++        int   v3 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(int, int, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, int, int, ptr)) {
++        /* Call: int func(int,int,ptr) */
++        int   v1 = va_arg(ap, va_type(int));
++        int   v2 = va_arg(ap, va_type(int));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(int, int, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, int, ptr, int)) {
++        /* Call: int func(int,ptr,int) */
++        int   v1 = va_arg(ap, va_type(int));
++        void *v2 = va_arg(ap, va_type(ptr));
++        int   v3 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(int, void *, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, int, ptr, ptr)) {
++        /* Call: int func(int,ptr,ptr) */
++        int   v1 = va_arg(ap, va_type(int));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(int, void *, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, ptr, int, int)) {
++        /* Call: int func(ptr,int,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        int   v3 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(void *, int, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, ptr, int, ptr)) {
++        /* Call: int func(ptr,int,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(void *, int, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, ptr, ptr, int)) {
++        /* Call: int func(ptr,ptr,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        int   v3 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(void *, void *, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(int, ptr, ptr, ptr)) {
++        /* Call: int func(ptr,ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(void *, void *, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, int, int, int)) {
++        /* Call: ptr func(int,int,int) */
++        int   v1 = va_arg(ap, va_type(int));
++        int   v2 = va_arg(ap, va_type(int));
++        int   v3 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(int, int, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, int, int, ptr)) {
++        /* Call: ptr func(int,int,ptr) */
++        int   v1 = va_arg(ap, va_type(int));
++        int   v2 = va_arg(ap, va_type(int));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(int, int, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, int, ptr, int)) {
++        /* Call: ptr func(int,ptr,int) */
++        int   v1 = va_arg(ap, va_type(int));
++        void *v2 = va_arg(ap, va_type(ptr));
++        int   v3 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(int, void *, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, int, ptr, ptr)) {
++        /* Call: ptr func(int,ptr,ptr) */
++        int   v1 = va_arg(ap, va_type(int));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(int, void *, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, ptr, int, int)) {
++        /* Call: ptr func(ptr,int,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        int   v3 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(void *, int, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, ptr, int, ptr)) {
++        /* Call: ptr func(ptr,int,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(void *, int, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, ptr, ptr, int)) {
++        /* Call: ptr func(ptr,ptr,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        int   v3 = va_arg(ap, va_type(int));
++        *((void * *)v_rc) = ((void *(*)(void *, void *, int))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(ptr, ptr, ptr, ptr)) {
++        /* Call: ptr func(ptr,ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(void *, void *, void *))(hf->hf_ptr))(v1, v2, v3);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG5(int, ptr, ptr, ptr, int)) {
++        /* Call: int func(ptr,ptr,ptr,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        int   v4 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(void *, void *, void *, int))(hf->hf_ptr))(v1, v2, v3, v4);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG6(int, ptr, ptr, ptr, int, ptr)) {
++        /* Call: int func(ptr,ptr,ptr,int,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        int   v4 = va_arg(ap, va_type(int));
++        void *v5 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(void *, void *, void *, int, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG6(int, ptr, ptr, ptr, ptr, int)) {
++        /* Call: int func(ptr,ptr,ptr,ptr,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        void *v4 = va_arg(ap, va_type(ptr));
++        int   v5 = va_arg(ap, va_type(int));
++        *((int *)v_rc) = ((int(*)(void *, void *, void *, void *, int))(hf->hf_ptr))(v1, v2, v3, v4, v5);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG7(int, ptr, ptr, ptr, ptr, int, ptr)) {
++        /* Call: int func(ptr,ptr,ptr,ptr,int,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        void *v4 = va_arg(ap, va_type(ptr));
++        int   v5 = va_arg(ap, va_type(int));
++        void *v6 = va_arg(ap, va_type(ptr));
++        *((int *)v_rc) = ((int(*)(void *, void *, void *, void *, int, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5, v6);
++        rc = (*((int *)v_rc) != he->he_modeval.v_int);
++    }
++    else if (he->he_sig == AP_HOOK_SIG6(ptr, ptr, ptr, ptr, ptr, ptr)) {
++        /* Call: ptr func(ptr,ptr,ptr,ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        void *v4 = va_arg(ap, va_type(ptr));
++        void *v5 = va_arg(ap, va_type(ptr));
++        *((void * *)v_rc) = ((void *(*)(void *, void *, void *, void *, void *))(hf->hf_ptr))(v1, v2, v3, v4, v5);
++        rc = (*((void * *)v_rc) != he->he_modeval.v_ptr);
++    }
++    else if (he->he_sig == AP_HOOK_SIG2(void, ptr)) {
++        /* Call: void func(ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        ((void(*)(void *))(hf->hf_ptr))(v1);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(void, ptr, int, int)) {
++        /* Call: void func(ptr,int,int) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        int   v2 = va_arg(ap, va_type(int));
++        int   v3 = va_arg(ap, va_type(int));
++        ((void(*)(void *, int, int))(hf->hf_ptr))(v1, v2, v3);
++    }
++    else if (he->he_sig == AP_HOOK_SIG3(void, ptr, ptr)) {
++        /* Call: void func(ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        ((void(*)(void *, void *))(hf->hf_ptr))(v1, v2);
++    }
++    else if (he->he_sig == AP_HOOK_SIG4(void, ptr, ptr, ptr)) {
++        /* Call: void func(ptr,ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        ((void(*)(void *, void *, void *))(hf->hf_ptr))(v1, v2, v3);
++    }
++    else if (he->he_sig == AP_HOOK_SIG5(void, ptr, ptr, ptr, ptr)) {
++        /* Call: void func(ptr,ptr,ptr,ptr) */
++        void *v1 = va_arg(ap, va_type(ptr));
++        void *v2 = va_arg(ap, va_type(ptr));
++        void *v3 = va_arg(ap, va_type(ptr));
++        void *v4 = va_arg(ap, va_type(ptr));
++        ((void(*)(void *, void *, void *, void *))(hf->hf_ptr))(v1, v2, v3, v4);
++    }
++    /* ----END GENERATED SECTION---------- */
++    else
++        ap_log_assert("hook signature not implemented", __FILE__, __LINE__);
++
++    if (he->he_modeid == AP_HOOK_MODE_ALL)
++        rc = FALSE;
++    else if (he->he_modeid == AP_HOOK_MODE_TOPMOST)
++        rc = TRUE;
++
++    return rc;
++}
++
++#endif /* EAPI */
++
++/*
++=cut
++##
++##  Embedded Perl script for generating the dispatch section
++##
++
++require 5.003;
++use strict;
++
++#   configuration
++my $file  = $0;
++my $begin = '----BEGIN GENERATED SECTION--------';
++my $end   = '----END GENERATED SECTION----------';
++
++#   special command: find used signatures
++if ($ARGV[0] eq 'used') {
++    my @S = `find .. -type f -name "*.c" -print`;
++    my $s;
++    my %T = ();
++    foreach $s (@S) {
++        $s =~ s|\n$||;
++        open(FP, "<$s") || die;
++        my $source = '';
++        $source .= $_ while (<FP>);
++        close(FP);
++        my %seen = ();
++        sub printme {
++            my ($src, $hook, $sig) = @_;
++            return if ($seen{$hook} == 1);
++            $seen{$hook} = 1;
++            my ($rc, $args) = ($sig =~ m|^([^,]+)(.*)$|);
++            $args =~ s|^,||;
++            $src =~ s|^.+/||;
++            my $sig = sprintf("%-6sfunc(%s)", $rc, $args);
++            $T{$sig}++; 
++        }
++        $source =~ s|\("([^"]+)",\s*AP_HOOK_SIG[0-9]\((.+?)\)|&printme($s, $1, $2), ''|sge;
++    }
++    my $t;
++    foreach $t (sort(keys(%T))) {
++        printf("     *    %-40s [%dx]\n", $t, $T{$t});
++    }
++    exit(0);
++}
++
++#   read ourself and keep a backup
++open(FP, "<$file") || die;
++my $source = '';
++$source .= $_ while (<FP>);
++close(FP);
++open(FP, ">$file.bak") || die;
++print FP $source;
++close(FP);
++
++#   now parse the signature lines and update the code
++my $o = '';
++my $next = 0;
++my $line;
++my %seen = ();
++foreach $line (split(/\n/, $source)) {
++    next if (not $line =~ m|\*\s+\S+\s+func\(.*\)|);
++    my ($sig, $rc, $param) = ($line =~ m|\*\s+((\S+)\s+func\((.*?)\))|);
++    $sig =~ s|\s+| |g;
++
++    next if ($seen{$sig} == 1);
++    $seen{$sig} = 1;
++
++    print "Generating code for `$sig'\n";
++
++    my @S = ($rc, split(/[\s,]+/, $param));
++    my @RS = @S;
++    my $i;
++    for ($i = 0; $i <= $#RS; $i++) {
++        $RS[$i] = 'void *' if ($RS[$i] eq 'ptr');
++        $RS[$i] = 'void *' if ($RS[$i] eq 'ctx');
++    }
++
++    $o .= "else " if ($next); $next++;
++    $o .= sprintf("if (he->he_sig == AP_HOOK_SIG%d(%s)) {\n", $#S+1, join(', ',@S));
++    $o .= sprintf("    \/\* Call: %s \*\/\n", $sig);
++    for ($i = 1; $i <= $#S; $i++) {
++        $o .= sprintf("    %-6sv%d = va_arg(ap, va_type(%s));\n", $RS[$i], $i, $S[$i]);
++    }
++    $o .= "    ";
++    $o .= sprintf("*((%s *)v_rc) = ", $RS[0]) if ($S[0] ne 'void');
++    $o .= sprintf("((%s(*)(%s))(hf->hf_ptr))", $RS[0], join(', ', @RS[1..$#RS]));
++    $o .= "(";
++    for ($i = 1; $i <= $#S; $i++) {
++        $o .= "hf->hf_ctx" if ($S[$i] eq 'ctx');
++        $o .= sprintf("v%d", $i) if ($S[$i] ne 'ctx');
++        $o .= ", " if ($i < $#S);
++    }
++    $o .= ");\n";
++    $o .= sprintf("    rc = (*((%s *)v_rc) != he->he_modeval.v_%s);\n", 
++                  $RS[0], $S[0]) if ($S[0] ne 'void');
++    $o .= "}\n";
++}
++
++#   insert the generated code at the target location
++$o =~ s|^|    |mg;
++$source =~ s|(\/\* $begin.+?\n).*\n(.*?\/\* $end)|$1$o$2|s;
++
++#   and update the source on disk
++print "Updating file `$file'\n";
++open(FP, ">$file") || die;
++print FP $source;
++close(FP);
++
++=pod
++*/
+diff -Nru apache_1.3.9/src/ap/ap_mm.c apache_1.3.9.EAPI/src/ap/ap_mm.c
+--- apache_1.3.9/src/ap/ap_mm.c        Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/ap/ap_mm.c   Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,178 @@
++/* ====================================================================
++ * Copyright (c) 1999 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ */
++
++/*
++**  ap_mm.c -- wrapper for MM shared memory library
++**
++**  This file has two reason:
++**
++**  1. Under DSO context we need stubs inside the Apache core code
++**     to make sure the MM library's code is actually available
++**     to the module DSOs.
++**
++**  2. When the MM library cannot be built on the current platform
++**     still provide dummy stubs so modules using the ap_mm_xxx()
++**     functions can be still built. But modules should use
++**     ap_mm_useable() to find out whether they really can use
++**     the MM stuff.
++*/
++                                       /*
++                                        * "What you see is all you get."
++                                        *     -- Brian Kernighan
++                                        */
++#ifdef EAPI
++
++#include "httpd.h"
++#include "ap_mm.h"
++
++#ifdef EAPI_MM
++#include "mm.h"
++API_EXPORT(int) ap_mm_useable(void) { return TRUE;  }
++#define STUB(val,nul)               { return val;   }
++#define STUB_STMT(stmt)             { stmt; return; }
++#else
++API_EXPORT(int) ap_mm_useable(void) { return FALSE; }
++#define STUB(val,nul)               { return nul;   }
++#define STUB_STMT(stmt)             { return;       }
++#endif
++
++API_EXPORT(int) ap_MM_create(size_t size, char *file) 
++    STUB(MM_create(size, file), FALSE)
++API_EXPORT(int) ap_MM_permission(mode_t mode, uid_t owner, gid_t group) 
++    STUB(MM_permission(mode, owner, group), -1)
++API_EXPORT(void) ap_MM_destroy(void)
++    STUB_STMT(MM_destroy())
++API_EXPORT(int) ap_MM_lock(ap_mm_lock_mode mode)
++    STUB(MM_lock(mode), FALSE)
++API_EXPORT(int) ap_MM_unlock(void)
++    STUB(MM_unlock(), FALSE)
++API_EXPORT(void *) ap_MM_malloc(size_t size)
++    STUB(MM_malloc(size), NULL)
++API_EXPORT(void *) ap_MM_realloc(void *ptr, size_t size)
++    STUB(MM_realloc(ptr, size), NULL)
++API_EXPORT(void) ap_MM_free(void *ptr)
++    STUB_STMT(MM_free(ptr))
++API_EXPORT(void *) ap_MM_calloc(size_t number, size_t size)
++    STUB(MM_calloc(number, size), NULL)
++API_EXPORT(char *) ap_MM_strdup(const char *str)
++    STUB(MM_strdup(str), NULL)
++API_EXPORT(size_t) ap_MM_sizeof(void *ptr)
++    STUB(MM_sizeof(ptr), 0)
++API_EXPORT(size_t) ap_MM_maxsize(void)
++    STUB(MM_maxsize(), 0)
++API_EXPORT(size_t) ap_MM_available(void)
++    STUB(MM_available(), 0)
++API_EXPORT(char *) ap_MM_error(void)
++    STUB(MM_error(), NULL)
++
++API_EXPORT(AP_MM *) ap_mm_create(size_t size, char *file)
++    STUB(mm_create(size, file), NULL)
++API_EXPORT(int) ap_mm_permission(AP_MM *mm, mode_t mode, uid_t owner, gid_t group) 
++    STUB(mm_permission(mm, mode, owner, group), -1)
++API_EXPORT(void) ap_mm_destroy(AP_MM *mm)
++    STUB_STMT(mm_destroy(mm))
++API_EXPORT(int) ap_mm_lock(AP_MM *mm, ap_mm_lock_mode mode)
++    STUB(mm_lock(mm, mode), FALSE)
++API_EXPORT(int) ap_mm_unlock(AP_MM *mm)
++    STUB(mm_unlock(mm), FALSE)
++API_EXPORT(void *) ap_mm_malloc(AP_MM *mm, size_t size)
++    STUB(mm_malloc(mm, size), NULL)
++API_EXPORT(void *) ap_mm_realloc(AP_MM *mm, void *ptr, size_t size)
++    STUB(mm_realloc(mm, ptr, size), NULL)
++API_EXPORT(void) ap_mm_free(AP_MM *mm, void *ptr)
++    STUB_STMT(mm_free(mm, ptr))
++API_EXPORT(void *) ap_mm_calloc(AP_MM *mm, size_t number, size_t size)
++    STUB(mm_calloc(mm, number, size), NULL)
++API_EXPORT(char *) ap_mm_strdup(AP_MM *mm, const char *str)
++    STUB(mm_strdup(mm, str), NULL)
++API_EXPORT(size_t) ap_mm_sizeof(AP_MM *mm, void *ptr)
++    STUB(mm_sizeof(mm, ptr), 0)
++API_EXPORT(size_t) ap_mm_maxsize(void)
++    STUB(mm_maxsize(), 0)
++API_EXPORT(size_t) ap_mm_available(AP_MM *mm)
++    STUB(mm_available(mm), 0)
++API_EXPORT(char *) ap_mm_error(void)
++    STUB(mm_error(), NULL)
++API_EXPORT(void) ap_mm_display_info(AP_MM *mm)
++    STUB_STMT(mm_display_info(mm))
++
++API_EXPORT(void *) ap_mm_core_create(size_t size, char *file)
++    STUB(mm_core_create(size, file), NULL)
++API_EXPORT(int) ap_mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group) 
++    STUB(mm_core_permission(core, mode, owner, group), -1)
++API_EXPORT(void) ap_mm_core_delete(void *core)
++    STUB_STMT(mm_core_delete(core))
++API_EXPORT(size_t) ap_mm_core_size(void *core)
++    STUB(mm_core_size(core), 0)
++API_EXPORT(int) ap_mm_core_lock(void *core, ap_mm_lock_mode mode)
++    STUB(mm_core_lock(core, mode), FALSE)
++API_EXPORT(int) ap_mm_core_unlock(void *core)
++    STUB(mm_core_unlock(core), FALSE)
++API_EXPORT(size_t) ap_mm_core_maxsegsize(void)
++    STUB(mm_core_maxsegsize(), 0)
++API_EXPORT(size_t) ap_mm_core_align2page(size_t size)
++    STUB(mm_core_align2page(size), 0)
++API_EXPORT(size_t) ap_mm_core_align2word(size_t size)
++    STUB(mm_core_align2word(size), 0)
++
++API_EXPORT(void) ap_mm_lib_error_set(unsigned int type, const char *str)
++    STUB_STMT(mm_lib_error_set(type, str))
++API_EXPORT(char *) ap_mm_lib_error_get(void)
++    STUB(mm_lib_error_get(), NULL)
++API_EXPORT(int) ap_mm_lib_version(void)
++    STUB(mm_lib_version(), 0)
++
++#endif /* EAPI */
+diff -Nru apache_1.3.9/src/include/alloc.h apache_1.3.9.EAPI/src/include/alloc.h
+--- apache_1.3.9/src/include/alloc.h   Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/alloc.h      Wed Dec 29 21:25:56 1999
+@@ -93,6 +93,15 @@
+ pool * ap_init_alloc(void);           /* Set up everything */
+ API_EXPORT(pool *) ap_make_sub_pool(pool *);  /* All pools are subpools of permanent_pool */
++#if defined(EAPI)
++typedef enum { AP_POOL_RD, AP_POOL_RW } ap_pool_lock_mode;
++int ap_shared_pool_possible(void);
++void ap_init_alloc_shared(int);
++void ap_kill_alloc_shared(void);
++API_EXPORT(pool *) ap_make_shared_sub_pool(pool *);
++API_EXPORT(int) ap_acquire_pool(pool *, ap_pool_lock_mode);
++API_EXPORT(int) ap_release_pool(pool *);
++#endif
+ API_EXPORT(void) ap_destroy_pool(pool *);
+ /* pools have nested lifetimes -- sub_pools are destroyed when the
+diff -Nru apache_1.3.9/src/include/ap_ctx.h apache_1.3.9.EAPI/src/include/ap_ctx.h
+--- apache_1.3.9/src/include/ap_ctx.h  Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/include/ap_ctx.h     Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,110 @@
++/* ====================================================================
++ * Copyright (c) 1998 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ *
++ */
++
++/*
++**  Generic Context Interface for Apache
++**  Written by Ralf S. Engelschall <rse@engelschall.com> 
++*/
++
++#ifdef EAPI
++
++#ifndef AP_CTX_H
++#define AP_CTX_H
++
++#ifndef FALSE
++#define FALSE 0
++#define TRUE  !FALSE
++#endif
++
++/*
++ * Internal Context Record Definition
++ */
++
++#define AP_CTX_MAX_ENTRIES 1024
++
++typedef struct {
++    char *ce_key;
++    void *ce_val;
++} ap_ctx_entry;
++
++typedef struct {
++    pool          *cr_pool;
++    ap_ctx_entry **cr_entry;
++} ap_ctx_rec;
++
++typedef ap_ctx_rec ap_ctx;
++
++/*
++ * Some convinience macros for storing _numbers_ 0...n in contexts, i.e.
++ * treating numbers as pointers but keeping track of the NULL return code of
++ * ap_ctx_get.
++ */
++#define AP_CTX_NUM2PTR(n) (void *)((unsigned int)(n)+1)
++#define AP_CTX_PTR2NUM(p) (unsigned int)(((char *)(p))-1)
++
++/*
++ * Prototypes for Context Handling Functions
++ */
++
++API_EXPORT(ap_ctx *)ap_ctx_new(pool *p);
++API_EXPORT(void)    ap_ctx_set(ap_ctx *ctx, char *key, void *val);
++API_EXPORT(void *)  ap_ctx_get(ap_ctx *ctx, char *key);
++API_EXPORT(ap_ctx *)ap_ctx_overlay(pool *p, ap_ctx *over, ap_ctx *base);
++
++#endif /* AP_CTX_H */
++
++#endif /* EAPI */
+diff -Nru apache_1.3.9/src/include/ap_hook.h apache_1.3.9.EAPI/src/include/ap_hook.h
+--- apache_1.3.9/src/include/ap_hook.h Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/include/ap_hook.h    Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,710 @@
++#if 0
++=cut
++#endif
++/* ====================================================================
++ * Copyright (c) 1998 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ *
++ */
++
++/*
++**  Implementation of a Generic Hook Interface for Apache
++**  Written by Ralf S. Engelschall <rse@engelschall.com> 
++**
++**  See POD document at end of this file for description.
++**  View it with the command ``pod2man ap_hook.h | nroff -man | more''
++**
++**  Attention: This header file is a little bit tricky.
++**             It's a combination of a C source and an embedded POD document
++**             The purpose of this is to have both things together at one
++**             place. So you can both pass this file to the C compiler and 
++**             the pod2man translater.
++*/
++
++#ifdef EAPI
++
++#ifndef AP_HOOK_H
++#define AP_HOOK_H
++
++/*
++ * Function Signature Specification:
++ *
++ * We encode the complete signature ingredients as a bitfield
++ * stored in a single unsigned long integer value, which can be
++ * constructed with AP_HOOK_SIGx(...)
++ */
++
++/* the type of the signature bitfield */
++typedef unsigned long int ap_hook_sig;
++
++/* the mask (bin) 111 (hex 0x7) for the triples in the bitfield */
++#define AP_HOOK_SIG_TRIPLE_MASK  0x7
++
++/* the position of the triple */
++#define AP_HOOK_SIG_TRIPLE_POS(n) ((n)*3)
++
++/* the constructor for triple #n with value v */
++#define AP_HOOK_SIG_TRIPLE(n,v) \
++        (((ap_hook_sig)(v))<<((AP_HOOK_##n)*3))
++
++/* the check whether triple #n in sig contains value v */
++#define AP_HOOK_SIG_HAS(sig,n,v) \
++        ((((ap_hook_sig)(sig))&AP_HOOK_SIG_TRIPLE(n, AP_HOOK_SIG_TRIPLE_MASK)) == (AP_HOOK_##n##_##v))
++
++/* utility function to get triple #n in sig */
++#define AP_HOOK_SIG_TRIPLE_GET(sig,n) \
++        ((((ap_hook_sig)(sig))>>AP_HOOK_SIG_TRIPLE_POS(n))&(AP_HOOK_SIG_TRIPLE_MASK))
++
++/* utility function to set triple #n in sig to value v */
++#define AP_HOOK_SIG_TRIPLE_SET(sig,n,v) \
++        ((((ap_hook_sig)(sig))&~(AP_HOOK_SIG_TRIPLE_MASK<<AP_HOOK_SIG_TRIPLE_POS(n)))|((v)<<AP_HOOK_SIG_TRIPLE_POS(n)))
++
++/* define the ingredients for the triple #0: id stuff */
++#define AP_HOOK_ID          0
++#define AP_HOOK_ID_ok       AP_HOOK_SIG_TRIPLE(ID,0)
++#define AP_HOOK_ID_undef    AP_HOOK_SIG_TRIPLE(ID,1)
++
++/* define the ingredients for the triple #1: return code */
++#define AP_HOOK_RC          1
++#define AP_HOOK_RC_void     AP_HOOK_SIG_TRIPLE(RC,0)
++#define AP_HOOK_RC_char     AP_HOOK_SIG_TRIPLE(RC,1)
++#define AP_HOOK_RC_int      AP_HOOK_SIG_TRIPLE(RC,2)
++#define AP_HOOK_RC_long     AP_HOOK_SIG_TRIPLE(RC,3)
++#define AP_HOOK_RC_float    AP_HOOK_SIG_TRIPLE(RC,4)
++#define AP_HOOK_RC_double   AP_HOOK_SIG_TRIPLE(RC,5)
++#define AP_HOOK_RC_ptr      AP_HOOK_SIG_TRIPLE(RC,6)
++
++/* define the ingredients for the triple #2: argument 1 */
++#define AP_HOOK_A1          2
++#define AP_HOOK_A1_ctx      AP_HOOK_SIG_TRIPLE(A1,0)
++#define AP_HOOK_A1_char     AP_HOOK_SIG_TRIPLE(A1,1)
++#define AP_HOOK_A1_int      AP_HOOK_SIG_TRIPLE(A1,2)
++#define AP_HOOK_A1_long     AP_HOOK_SIG_TRIPLE(A1,3)
++#define AP_HOOK_A1_float    AP_HOOK_SIG_TRIPLE(A1,4)
++#define AP_HOOK_A1_double   AP_HOOK_SIG_TRIPLE(A1,5)
++#define AP_HOOK_A1_ptr      AP_HOOK_SIG_TRIPLE(A1,6)
++
++/* define the ingredients for the triple #3: argument 2 */
++#define AP_HOOK_A2          3
++#define AP_HOOK_A2_ctx      AP_HOOK_SIG_TRIPLE(A2,0)
++#define AP_HOOK_A2_char     AP_HOOK_SIG_TRIPLE(A2,1)
++#define AP_HOOK_A2_int      AP_HOOK_SIG_TRIPLE(A2,2)
++#define AP_HOOK_A2_long     AP_HOOK_SIG_TRIPLE(A2,3)
++#define AP_HOOK_A2_float    AP_HOOK_SIG_TRIPLE(A2,4)
++#define AP_HOOK_A2_double   AP_HOOK_SIG_TRIPLE(A2,5)
++#define AP_HOOK_A2_ptr      AP_HOOK_SIG_TRIPLE(A2,6)
++
++/* define the ingredients for the triple #4: argument 3 */
++#define AP_HOOK_A3          4
++#define AP_HOOK_A3_ctx      AP_HOOK_SIG_TRIPLE(A3,0)
++#define AP_HOOK_A3_char     AP_HOOK_SIG_TRIPLE(A3,1)
++#define AP_HOOK_A3_int      AP_HOOK_SIG_TRIPLE(A3,2)
++#define AP_HOOK_A3_long     AP_HOOK_SIG_TRIPLE(A3,3)
++#define AP_HOOK_A3_float    AP_HOOK_SIG_TRIPLE(A3,4)
++#define AP_HOOK_A3_double   AP_HOOK_SIG_TRIPLE(A3,5)
++#define AP_HOOK_A3_ptr      AP_HOOK_SIG_TRIPLE(A3,6)
++
++/* define the ingredients for the triple #5: argument 4 */
++#define AP_HOOK_A4          5
++#define AP_HOOK_A4_ctx      AP_HOOK_SIG_TRIPLE(A4,0)
++#define AP_HOOK_A4_char     AP_HOOK_SIG_TRIPLE(A4,1)
++#define AP_HOOK_A4_int      AP_HOOK_SIG_TRIPLE(A4,2)
++#define AP_HOOK_A4_long     AP_HOOK_SIG_TRIPLE(A4,3)
++#define AP_HOOK_A4_float    AP_HOOK_SIG_TRIPLE(A4,4)
++#define AP_HOOK_A4_double   AP_HOOK_SIG_TRIPLE(A4,5)
++#define AP_HOOK_A4_ptr      AP_HOOK_SIG_TRIPLE(A4,6)
++
++/* define the ingredients for the triple #6: argument 5 */
++#define AP_HOOK_A5          6
++#define AP_HOOK_A5_ctx      AP_HOOK_SIG_TRIPLE(A5,0)
++#define AP_HOOK_A5_char     AP_HOOK_SIG_TRIPLE(A5,1)
++#define AP_HOOK_A5_int      AP_HOOK_SIG_TRIPLE(A5,2)
++#define AP_HOOK_A5_long     AP_HOOK_SIG_TRIPLE(A5,3)
++#define AP_HOOK_A5_float    AP_HOOK_SIG_TRIPLE(A5,4)
++#define AP_HOOK_A5_double   AP_HOOK_SIG_TRIPLE(A5,5)
++#define AP_HOOK_A5_ptr      AP_HOOK_SIG_TRIPLE(A5,6)
++
++/* define the ingredients for the triple #7: argument 6 */
++#define AP_HOOK_A6          7
++#define AP_HOOK_A6_ctx      AP_HOOK_SIG_TRIPLE(A6,0)
++#define AP_HOOK_A6_char     AP_HOOK_SIG_TRIPLE(A6,1)
++#define AP_HOOK_A6_int      AP_HOOK_SIG_TRIPLE(A6,2)
++#define AP_HOOK_A6_long     AP_HOOK_SIG_TRIPLE(A6,3)
++#define AP_HOOK_A6_float    AP_HOOK_SIG_TRIPLE(A6,4)
++#define AP_HOOK_A6_double   AP_HOOK_SIG_TRIPLE(A6,5)
++#define AP_HOOK_A6_ptr      AP_HOOK_SIG_TRIPLE(A6,6)
++
++/* define the ingredients for the triple #8: argument 7 */
++#define AP_HOOK_A7          8
++#define AP_HOOK_A7_ctx      AP_HOOK_SIG_TRIPLE(A7,0)
++#define AP_HOOK_A7_char     AP_HOOK_SIG_TRIPLE(A7,1)
++#define AP_HOOK_A7_int      AP_HOOK_SIG_TRIPLE(A7,2)
++#define AP_HOOK_A7_long     AP_HOOK_SIG_TRIPLE(A7,3)
++#define AP_HOOK_A7_float    AP_HOOK_SIG_TRIPLE(A7,4)
++#define AP_HOOK_A7_double   AP_HOOK_SIG_TRIPLE(A7,5)
++#define AP_HOOK_A7_ptr      AP_HOOK_SIG_TRIPLE(A7,6)
++
++/* define the ingredients for the triple #9: argument 8 */
++#define AP_HOOK_A8          9
++#define AP_HOOK_A8_ctx      AP_HOOK_SIG_TRIPLE(9,0)
++#define AP_HOOK_A8_char     AP_HOOK_SIG_TRIPLE(9,1)
++#define AP_HOOK_A8_int      AP_HOOK_SIG_TRIPLE(9,2)
++#define AP_HOOK_A8_long     AP_HOOK_SIG_TRIPLE(9,3)
++#define AP_HOOK_A8_float    AP_HOOK_SIG_TRIPLE(9,4)
++#define AP_HOOK_A8_double   AP_HOOK_SIG_TRIPLE(9,5)
++#define AP_HOOK_A8_ptr      AP_HOOK_SIG_TRIPLE(9,6)
++  
++/* the constructor for unknown signatures */
++#define AP_HOOK_SIG_UNKNOWN AP_HOOK_ID_undef
++
++/* the constructor for signatures with 1 type */
++#define AP_HOOK_SIG1(rc) \
++        (AP_HOOK_RC_##rc)
++
++/* the constructor for signatures with 2 types */
++#define AP_HOOK_SIG2(rc,a1) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1)
++
++/* the constructor for signatures with 3 types */
++#define AP_HOOK_SIG3(rc,a1,a2) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2)
++
++/* the constructor for signatures with 4 types */
++#define AP_HOOK_SIG4(rc,a1,a2,a3) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3)
++
++/* the constructor for signatures with 5 types */
++#define AP_HOOK_SIG5(rc,a1,a2,a3,a4) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4)
++
++/* the constructor for signatures with 6 types */
++#define AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5)
++
++/* the constructor for signatures with 7 types */
++#define AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6)
++
++/* the constructor for signatures with 8 types */
++#define AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6|AP_HOOK_A7_##a7)
++
++/* the constructor for signatures with 9 types */
++#define AP_HOOK_SIG9(rc,a1,a2,a3,a4,a5,a6,a7,a8) \
++        (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6|AP_HOOK_A7_##a7|AP_HOOK_A8_##a8)
++
++/*
++ * Return Value Mode Identification
++ */
++
++/* the type of the return value modes */
++typedef unsigned int ap_hook_mode;
++
++/* the mode of the return value */
++#define AP_HOOK_MODE_UNKNOWN  0
++#define AP_HOOK_MODE_TOPMOST  1
++#define AP_HOOK_MODE_DECLINE  2
++#define AP_HOOK_MODE_DECLTMP  3
++#define AP_HOOK_MODE_ALL      4
++
++/* the constructors for the return value modes */
++#define AP_HOOK_TOPMOST       AP_HOOK_MODE_TOPMOST
++#define AP_HOOK_DECLINE(val)  AP_HOOK_MODE_DECLINE, (val)   
++#define AP_HOOK_DECLTMP(val)  AP_HOOK_MODE_DECLTMP, (val)   
++#define AP_HOOK_ALL           AP_HOOK_MODE_ALL
++
++/*
++ * Hook State Identification
++ */
++
++/* the type of the hook state */
++typedef unsigned short int ap_hook_state;
++
++/* the values of the hook state */
++#define AP_HOOK_STATE_UNDEF       0
++#define AP_HOOK_STATE_NOTEXISTANT 1
++#define AP_HOOK_STATE_ESTABLISHED 2
++#define AP_HOOK_STATE_CONFIGURED  3
++#define AP_HOOK_STATE_REGISTERED  4
++
++/*
++ * Hook Context Identification
++ *
++ * Notice: Null is ok here, because AP_HOOK_NOCTX is just a dummy argument
++ *         because we know from the signature whether the argument is a
++ *         context value or just the dummy value.
++ */
++
++#define AP_HOOK_NOCTX  (void *)(0)
++#define AP_HOOK_CTX(v) (void *)(v)
++
++/*
++ * Internal Hook Record Definition
++ */
++
++/* the union holding the arbitrary decline values */
++typedef union {
++    char   v_char;
++    int    v_int;
++    long   v_long;
++    float  v_float;
++    double v_double;
++    void  *v_ptr;
++} ap_hook_value;
++
++/* the structure holding one hook function and its context */
++typedef struct {
++    void *hf_ptr;              /* function pointer       */
++    void *hf_ctx;              /* function context       */
++} ap_hook_func;
++
++/* the structure holding one hook entry with all its registered functions */
++typedef struct {
++    char          *he_hook;    /* hook name (=unique id) */
++    ap_hook_sig    he_sig;     /* hook signature         */
++    int            he_modeid;  /* hook mode id           */
++    ap_hook_value  he_modeval; /* hook mode value        */
++    ap_hook_func **he_func;    /* hook registered funcs  */
++} ap_hook_entry;
++
++/* the maximum number of hooks and functions per hook */
++#define AP_HOOK_MAX_ENTRIES 512
++#define AP_HOOK_MAX_FUNCS   128
++
++/*
++ * Extended Variable Argument (vararg) Support
++ *
++ * In ANSI C varargs exists, but because the prototypes of function with
++ * varargs cannot reflect the types of the varargs, K&R argument passing
++ * conventions have to apply for the compiler.  This means mainly a conversion
++ * of shorter type variants to the maximum variant (according to sizeof). The
++ * above va_type() macro provides this mapping from the wanted types to the
++ * physically used ones.
++ */
++
++/* the mapping */
++#define VA_TYPE_char   int
++#define VA_TYPE_short  int
++#define VA_TYPE_int    int
++#define VA_TYPE_long   long
++#define VA_TYPE_float  double
++#define VA_TYPE_double double
++#define VA_TYPE_ptr    void *
++#define VA_TYPE_ctx    void *
++
++/* the constructor */
++#ifdef  va_type
++#undef  va_type
++#endif
++#define va_type(type)  VA_TYPE_ ## type
++
++/*
++ * Miscellaneous stuff
++ */
++
++#ifndef FALSE
++#define FALSE 0
++#define TRUE  !FALSE
++#endif
++
++/*
++ * Wrapper macros for the callback-function register/unregister calls.  
++ * 
++ * Background: Strict ANSI C doesn't allow a function pointer to be treated as
++ * a void pointer on argument passing, but we cannot declare the argument as a
++ * function prototype, because the functions can have arbitrary signatures. So
++ * we have to use a void pointer here. But to not require explicit casts on
++ * function pointers for every register/unregister call, we smooth the API a
++ * little bit by providing these macros.
++ */
++
++#define ap_hook_register(hook,func,ctx) ap_hook_register_I(hook,(void *)(func),ctx)
++#define ap_hook_unregister(hook,func)   ap_hook_unregister_I(hook,(void *)(func))
++
++/*
++ * Prototypes for the hook API functions
++ */
++
++API_EXPORT(void)          ap_hook_init         (void);
++API_EXPORT(void)          ap_hook_kill         (void);
++API_EXPORT(int)           ap_hook_configure    (char *hook, ap_hook_sig sig, ap_hook_mode modeid, ...);
++API_EXPORT(int)           ap_hook_register_I   (char *hook, void *func, void *ctx);
++API_EXPORT(int)           ap_hook_unregister_I (char *hook, void *func);
++API_EXPORT(ap_hook_state) ap_hook_status       (char *hook);
++API_EXPORT(int)           ap_hook_use          (char *hook, ap_hook_sig sig, ap_hook_mode modeid, ...);
++API_EXPORT(int)           ap_hook_call         (char *hook, ...);
++
++#endif /* AP_HOOK_H */
++
++#endif /* EAPI */
++/*
++=pod
++##
++##  Embedded POD document
++##
++
++=head1 NAME
++
++B<ap_hook> - B<Generic Hook Interface for Apache>
++
++=head1 SYNOPSIS
++
++B<Hook Library Setup:>
++
++ void ap_hook_init(void);
++ void ap_hook_kill(void);
++
++B<Hook Configuration and Registration:>
++
++ int ap_hook_configure(char *hook, ap_hook_sig sig, ap_hook_mode mode);
++ int ap_hook_register(char *hook, void *func, void *ctx);
++ int ap_hook_unregister(char *hook, void *func);
++
++B<Hook Usage:>
++
++ ap_hook_state ap_hook_status(char *hook);
++ int ap_hook_use(char *hook, ap_hook_sig sig, ap_hook_mode mode, ...);
++ int ap_hook_call(char *hook, ...);
++
++B<Hook Signature Constructors> (ap_hook_sig):
++
++ AP_HOOK_SIG1(rc)
++ AP_HOOK_SIG2(rc,a1)
++ AP_HOOK_SIG3(rc,a1,a2)
++ AP_HOOK_SIG4(rc,a1,a2,a3)
++ AP_HOOK_SIG5(rc,a1,a2,a3,a4)
++ AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5)
++ AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6)
++ AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7)
++
++B<Hook Modes Constructors> (ap_hook_mode):
++
++ AP_HOOK_TOPMOST
++ AP_HOOK_DECLINE(value)
++ AP_HOOK_DECLTMP(value)
++ AP_HOOK_ALL
++
++B<Hook States> (ap_hook_state):
++
++ AP_HOOK_STATE_UNDEF
++ AP_HOOK_STATE_NOTEXISTANT
++ AP_HOOK_STATE_ESTABLISHED
++ AP_HOOK_STATE_CONFIGURED 
++ AP_HOOK_STATE_REGISTERED
++
++=head1 DESCRIPTION
++
++This library implements a generic hook interface for Apache which can be used
++to loosely couple code through arbitrary hooks. There are two use cases for
++this mechanism:
++
++=over 3
++
++=item B<1. Extension and Overrides>
++
++Inside a specific code section you want to perform a specific function call
++for extension reasons.  But you want to allow one or more modules to implement
++this function by registering hooks. Those hooks are registered on a stack and
++can be even configured to have a I<decline> return value. As long as there are
++functions which return the decline value the next function on the stack is
++tried. When the first function doesn't return the decline value the hook call
++stops. 
++
++The original intent of this use case is to provide a flexible extension
++mechanism where modules can override functionality.
++
++=item B<2. Intercommunication>
++
++Inside a specific code you have a function you want to export. But you first
++want to allow other code to override this function.  And second you want to
++export this function without real object file symbol references. Instead you
++want to register the function and let the users call this function by name. 
++
++The original intent of this use case is to allow inter-module communication
++without direct symbol references, which are a big I<no-no> for the I<Dynamic
++Shared Object> (DSO) situation.
++
++=back
++
++And the following design goals existed:
++
++=over 3
++
++=item B<1. Minimum code changes>
++
++The hook calls should look very similar to the corresponding direct function
++call to allow one to easily translate it. And the total amount of changes for
++the hook registration, hook configuration and hook usage should be as small as
++possible to minimize the total code changes. Additionally a shorthand API
++function (ap_hook_use) should be provided which lets one trivially add a hook
++by just changing the code at a single location.
++
++=item B<2. The hook call has to be maximum flexible>
++
++In order to avoid nasty hacks, maximum flexiblity for the hook calls is
++needed, i.e. any function signature (the set of types for the return value and
++the arguments) should be supported.  And it should be possible to
++register always a context (ctx) variable with a function which is passed to
++the corresponding function when the hook call is performed.
++
++=back
++
++The implementation of this library directly followed these two design goals.
++
++=head1 USAGE
++
++Using this hook API is a four-step process:
++
++=over 3
++
++=item B<1. Initialization>
++
++Initialize or destroy the hook mechanism inside your application program:
++
++ ap_hook_init();
++    :
++ ap_hook_kill();
++
++=item B<2. Configuration>
++
++Configure a particular hook by specifing its name, signature and return type
++semantic:
++
++ ap_hook_configure("lookup", AP_HOOK_SIG2(ptr,ptr,ctx), AP_HOOK_DECLINE(NULL));
++ ap_hook_configure("setup", AP_HOOK_SIG2(int,ptr,char), AP_HOOK_DECLTMP(FALSE));
++ ap_hook_configure("read", AP_HOOK_SIG2(void,ptr), AP_HOOK_TOPMOST);
++ ap_hook_configure("logit", AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL);
++
++This configures four hooks: 
++
++A hook named C<lookup> with the signature C<void *lookup(void *, void *)>
++(where the second argument is C<NULL> or the private context pointer of the
++hook function which can be optionally provided at the registration step
++later) and a return code semantic which says: Proceed as long as the
++registered lookup functions return C<NULL> or no more registered functions
++exists. A call for this hook has to provide 2 argument only (a pointer to the
++return variable and the first argument), because the context is
++implicitly provided by the hook mechanism. Sample idea: I<The first function
++who was successful in looking up a variable provides the value>.
++
++A hook named C<setup> with the signature C<int setup(void *, char)" and a
++return code semantic equal to the one of the C<lookup> hook. But the decline
++return value is implemented by a temporay variable of the hook mechanism and
++only used for the decline decision. So a call to this hook has to provide 2
++arguments only (the first and second argument, but no address to a return
++value). Sample idea: I<Any function can handle the setup and when one
++function handled it stops the processing by indicating this with the return
++value>.
++
++A hook named C<read> with the signature C<void read(void *)> and a return code
++semantic which says: Only the top most function on the registered function
++stack is tried (and independet of a possible return value in non-void
++context). A call to this hook has to provide exactly 1 argument (the
++single argument to the hook function). Sample idea: I<We want to
++use a read function and allow others to override it, but independent how much
++registered functions exists, only top most (= last registered) function
++overrides and is used>.
++
++A hook named C<logit> with the signature C<void logit(void *)> and a return
++code semantic which says: All registered functions on the hook functioin stack
++are tried. Sample idea: I<We pass a FILE pointer to the logging functions and
++any function can log whatever it wants>.
++
++=item B<3. Registration>
++
++Register the actual functions which should be used by the hook:
++
++ ap_hook_register("lookup", mylookup, mycontext);
++ ap_hook_register("setup", mysetup);
++ ap_hook_register("read", myread);
++ ap_hook_register("logit", mylogit);
++
++This registers the function C<mylookup()> under the C<lookup> hook with the
++private context given by the variable C<mycontext>. And it registers the
++function C<mysetup()> under the C<setup> hook without any context. Same for
++C<myread> and C<mylogit>.
++
++=item B<4. Usage>
++
++Finally use the hooks, i.e. instead of using direct function calls like
++        
++ rc = mylookup(a1, a2);
++ rc = mysetup(a1, a2);
++ myread(a1);
++ mylogit(a1);
++
++you now use:
++
++ ap_hook_call("lookup", &rc, a1, a2);
++ ap_hook_call("setup", &rc, a1, a2);
++ ap_hook_call("read", a1);
++ ap_hook_call("logit", a1);
++
++which are internally translated to:
++
++ rc = mylookup(a1, a2, mycontext);
++ rc = mysetup(a1, a2);
++ myread(a1);
++ mylogit(a1);
++
++Notice two things here: First the context (C<mycontext>) for the C<mylookup()>
++function is automatically added by the hook mechanism. And it is a different
++(and not fixed) context for each registered function, of course.  Second,
++return values always have to be pushed into variables and a pointer to them
++has to be given as the second argument to C<ap_hook_call> (except for
++functions which have a void return type, of course).
++
++BTW, the return value of C<ap_hook_call()> is always C<TRUE> or C<FALSE>.
++C<TRUE> when at least one function call was successful (always the case for
++C<AP_HOOK_TOPMOST> and C<AP_HOOK_ALL>). C<FALSE> when all functions
++returned the decline value or no functions are registered at all.
++
++=back
++
++=head1 RESTRICTIONS
++
++To make the hook implementation efficient and to not bloat up the code too
++much a few restrictions have to make:
++
++=over 3
++
++=item 1.
++
++Only function calls with up to 4 arguments are implemented. When more are
++needed you can either extend the hook implementation by using more bits for
++the signature configuration or you can do a workaround when the function is
++your own one: Put the remaining (N-4-1) arguments into a structure and pass
++only a pointer (one argument) as the forth argument.
++
++=item 2.
++
++Only the following ANSI C variable types are supported:
++
++ - For the return value: 
++   void (= none), char, int, float, double, ptr (= void *)
++ - For the arguments:
++   ctx  (= context), char, int, float, double, ptr (= void *)
++
++This means in theory that 6^5 (=7776) signature combinations are possible. But
++because we don't need all of them inside Apache and it would bloat up the code
++too dramatically we implement only a subset of those combinations. The
++implemented signatures can be specified inside C<ap_hook.c> and the
++corresponding code can be automatically generated by running ``C<perl
++ap_hook.c>'' (yeah, no joke ;-).  So when you need a hook with a different
++still not implemented signature you either have to again use a workaround as
++above (i.e. use a structure) or just add the signature to the C<ap_hook.c>
++file.
++
++=head1 EXAMPLE
++
++We want to call `C<ssize_t read(int, void *, size_t)>' through hooks in order
++to allow modules to override this call.  So, somewhere we have a replacement
++function for C<read()> defined (same signature, of course):
++
++ ssize_t my_read(int, void *, size_t);
++
++We now configure a C<read> hook. Here the C<AP_HOOK_SIGx()> macro defines the
++signature of the C<read()>-like callback functions and has to match the
++prototype of C<read()>. But we have to replace typedefs with the physical
++underlaying ANSI C types. And C<AP_HOOK_DECLINE()> sets the return value of
++the read()-like functions which forces the next hook to be called (here -1).
++And we register the original C<read()> function as the default hook.
++
++ ap_hook_configure("read", 
++                   AP_HOOK_SIG4(int,int,ptr,int), 
++                   AP_HOOK_DECLINE(-1));
++ ap_hook_register("read", read);
++
++Now a module wants to override the C<read()> call and registers the
++C<my_read()> function:
++
++ ap_hook_register("read", my_read);
++
++The function logically gets pushed onto a stack, so the execution order is the
++reverse registering order, i.e. I<last registered - first called>. Now we can
++replace the standard C<read()> call
++
++ bytes = read(fd, buf, bufsize);
++ if (bytes == -1)
++    ...error...
++
++with the hook based call:
++
++  rc = ap_hook_call("read", &bytes, fd, buf, bufsize);
++  if (rc == FALSE)
++     ...error...
++
++Now internally the following is done: The call `C<bytes = my_read(fd, buf,
++bufsize)>' is done. When it returns not -1 (the decline value) nothing
++more is done. But when C<my_read()> returns -1 the next function is tried:
++`C<bytes = read(fd, buf, bufsize)>'. When this one also returns -1 you get
++`rc == FALSE'. When it finally returns not -1 you get `rc == TRUE'.
++
++=head1 SEE ALSO
++
++ap_ctx(3)
++
++=head1 HISTORY
++
++The ap_hook(3) interface was originally designed and implemented in October
++1998 by Ralf S. Engelschall as part of the mod_ssl project.
++
++=head1 AUTHOR
++
++ Ralf S. Engelschall
++ rse@engelschall.com
++ www.engelschall.com
++
++=cut
++*/
+diff -Nru apache_1.3.9/src/include/ap_mm.h apache_1.3.9.EAPI/src/include/ap_mm.h
+--- apache_1.3.9/src/include/ap_mm.h   Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/include/ap_mm.h      Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,130 @@
++/* ====================================================================
++ * Copyright (c) 1999 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ */
++
++/*
++**
++** ap_mm.h -- wrapper code for MM shared memory library
++**
++*/
++
++#ifdef EAPI
++
++#ifndef AP_MM_H 
++#define AP_MM_H 1
++
++#ifndef FALSE
++#define FALSE 0
++#define TRUE  !FALSE
++#endif
++
++API_EXPORT(int) ap_mm_useable(void);
++
++typedef void AP_MM;
++typedef enum { AP_MM_LOCK_RD, AP_MM_LOCK_RW } ap_mm_lock_mode;
++
++/* Global Malloc-Replacement API */
++API_EXPORT(int)     ap_MM_create(size_t size, char *file);
++API_EXPORT(int)     ap_MM_permission(mode_t mode, uid_t owner, gid_t group);
++API_EXPORT(void)    ap_MM_destroy(void);
++API_EXPORT(int)     ap_MM_lock(ap_mm_lock_mode mode);
++API_EXPORT(int)     ap_MM_unlock(void);
++API_EXPORT(void *)  ap_MM_malloc(size_t size);
++API_EXPORT(void *)  ap_MM_realloc(void *ptr, size_t size);
++API_EXPORT(void)    ap_MM_free(void *ptr);
++API_EXPORT(void *)  ap_MM_calloc(size_t number, size_t size);
++API_EXPORT(char *)  ap_MM_strdup(const char *str);
++API_EXPORT(size_t)  ap_MM_sizeof(void *ptr);
++API_EXPORT(size_t)  ap_MM_maxsize(void);
++API_EXPORT(size_t)  ap_MM_available(void);
++API_EXPORT(char *)  ap_MM_error(void);
++
++/* Standard Malloc-Style API */
++API_EXPORT(AP_MM *) ap_mm_create(size_t size, char *file);
++API_EXPORT(int)     ap_mm_permission(AP_MM *mm, mode_t mode, uid_t owner, gid_t group);
++API_EXPORT(void)    ap_mm_destroy(AP_MM *mm);
++API_EXPORT(int)     ap_mm_lock(AP_MM *mm, ap_mm_lock_mode mode);
++API_EXPORT(int)     ap_mm_unlock(AP_MM *mm);
++API_EXPORT(void *)  ap_mm_malloc(AP_MM *mm, size_t size);
++API_EXPORT(void *)  ap_mm_realloc(AP_MM *mm, void *ptr, size_t size);
++API_EXPORT(void)    ap_mm_free(AP_MM *mm, void *ptr);
++API_EXPORT(void *)  ap_mm_calloc(AP_MM *mm, size_t number, size_t size);
++API_EXPORT(char *)  ap_mm_strdup(AP_MM *mm, const char *str);
++API_EXPORT(size_t)  ap_mm_sizeof(AP_MM *mm, void *ptr);
++API_EXPORT(size_t)  ap_mm_maxsize(void);
++API_EXPORT(size_t)  ap_mm_available(AP_MM *mm);
++API_EXPORT(char *)  ap_mm_error(void);
++API_EXPORT(void)    ap_mm_display_info(AP_MM *mm);
++
++/* Low-Level Shared Memory API */
++API_EXPORT(void *)  ap_mm_core_create(size_t size, char *file);
++API_EXPORT(int)     ap_mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group);
++API_EXPORT(void)    ap_mm_core_delete(void *core);
++API_EXPORT(size_t)  ap_mm_core_size(void *core);
++API_EXPORT(int)     ap_mm_core_lock(void *core, ap_mm_lock_mode mode);
++API_EXPORT(int)     ap_mm_core_unlock(void *core);
++API_EXPORT(size_t)  ap_mm_core_maxsegsize(void);
++API_EXPORT(size_t)  ap_mm_core_align2page(size_t size);
++API_EXPORT(size_t)  ap_mm_core_align2word(size_t size);
++
++/* Internal Library API */
++API_EXPORT(void)    ap_mm_lib_error_set(unsigned int, const char *str);
++API_EXPORT(char *)  ap_mm_lib_error_get(void);
++API_EXPORT(int)     ap_mm_lib_version(void);
++
++#endif /* AP_MM_H */
++
++#endif /* EAPI */
++
+diff -Nru apache_1.3.9/src/include/ap_mmn.h apache_1.3.9.EAPI/src/include/ap_mmn.h
+--- apache_1.3.9/src/include/ap_mmn.h  Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/ap_mmn.h     Wed Dec 29 21:25:56 1999
+@@ -228,7 +228,23 @@
+  *                        ap_pbase64decode(), ap_pbase64encode()
+  */
++/* 
++ * Under Extended API situations we replace the magic cookie "AP13" with
++ * "EAPI" to let us distinguish between the EAPI module structure (which
++ * contain additional pointers at the end) and standard module structures
++ * (which lack at least NULL's for the pointers at the end).  This is
++ * important because standard ("AP13") modules would dump core when we
++ * dispatch over the additional hooks because NULL's are missing at the end of
++ * the module structure. See also the code in mod_so for details on loading
++ * (we accept both "AP13" and "EAPI").
++ */
++#ifdef EAPI
++#define MODULE_MAGIC_COOKIE_AP13 0x41503133UL /* "AP13" */
++#define MODULE_MAGIC_COOKIE_EAPI 0x45415049UL /* "EAPI" */
++#define MODULE_MAGIC_COOKIE      MODULE_MAGIC_COOKIE_EAPI 
++#else
+ #define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */
++#endif
+ #ifndef MODULE_MAGIC_NUMBER_MAJOR
+ #define MODULE_MAGIC_NUMBER_MAJOR 19990320
+diff -Nru apache_1.3.9/src/include/buff.h apache_1.3.9.EAPI/src/include/buff.h
+--- apache_1.3.9/src/include/buff.h    Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/buff.h       Wed Dec 29 21:25:56 1999
+@@ -124,6 +124,10 @@
+     /* transport handle, for RPC binding handle or some such */
+     void *t_handle;
++#ifdef EAPI
++    ap_ctx *ctx;
++#endif /* EAPI */
++
+ #ifdef B_SFIO
+     Sfio_t *sf_in;
+     Sfio_t *sf_out;
+@@ -175,6 +179,10 @@
+ /* Internal routines */
+ API_EXPORT(int) ap_bflsbuf(int c, BUFF *fb);
+ API_EXPORT(int) ap_bfilbuf(BUFF *fb);
++
++#ifdef EAPI
++#define ap_bpeekc(fb) ( ((fb)->incnt == 0) ? EOF : *((fb)->inptr) )
++#endif
+ #ifndef CHARSET_EBCDIC
+diff -Nru apache_1.3.9/src/include/http_conf_globals.h apache_1.3.9.EAPI/src/include/http_conf_globals.h
+--- apache_1.3.9/src/include/http_conf_globals.h       Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/http_conf_globals.h  Wed Dec 29 21:25:56 1999
+@@ -89,6 +89,9 @@
+ extern int ap_listenbacklog;
+ extern int ap_dump_settings;
+ extern API_VAR_EXPORT int ap_extended_status;
++#ifdef EAPI
++extern API_VAR_EXPORT ap_ctx *ap_global_ctx;
++#endif /* EAPI */
+ extern char *ap_pid_fname;
+ extern char *ap_scoreboard_fname;
+diff -Nru apache_1.3.9/src/include/http_config.h apache_1.3.9.EAPI/src/include/http_config.h
+--- apache_1.3.9/src/include/http_config.h     Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/http_config.h        Wed Dec 29 21:25:56 1999
+@@ -275,6 +275,65 @@
+     void (*child_exit) (server_rec *, pool *);
+ #endif
+     int (*post_read_request) (request_rec *);
++
++#ifdef EAPI
++    /*
++     * ANSI C guarantees us that we can at least _extend_ the module structure
++     * with additional hooks without the need to change all existing modules.
++     * Because: ``If there are fewer initializers in the list than members of
++     * the structure, the trailing members are initialized with 0.'' (The C
++     * Programming Language, 2nd Ed., A8.7 Initialization). So we just
++     * have to put our additional hooks here:
++     *
++     * add_module: 
++     *     Called from within ap_add_module() right after the module structure
++     *     was linked into the Apache internal module list.  It is mainly
++     *     intended to be used to define configuration defines (<IfDefine>)
++     *     which have to be available directly after a LoadModule/AddModule.
++     *     Actually this is the earliest possible hook a module can use.
++     *
++     * remove_module: 
++     *     Called from within ap_remove_module() right before the module
++     *     structure is kicked out from the Apache internal module list.
++     *     Actually this is last possible hook a module can use and exists for
++     *     consistency with the add_module hook.
++     *
++     * rewrite_command:
++     *     Called right after a configuration directive line was read and
++     *     before it is processed. It is mainly intended to be used for
++     *     rewriting directives in order to provide backward compatibility to
++     *     old directive variants.
++     *
++     * new_connection:
++     *     Called from within the internal new_connection() function, right
++     *     after the conn_rec structure for the new established connection was
++     *     created and before Apache starts processing the request with
++     *     ap_read_request().  It is mainly intended to be used to setup/run
++     *     connection dependent things like sending start headers for
++     *     on-the-fly compression, etc.
++     *
++     * close_connection:
++     *     Called from within the Apache dispatching loop just before any
++     *     ap_bclose() is performed on the socket connection, but a long time
++     *     before any pool cleanups are done for the connection (which can be
++     *     too late for some applications).  It is mainly intended to be used
++     *     to close/finalize connection dependent things like sending end
++     *     headers for on-the-fly compression, etc.
++     */
++#ifdef ULTRIX_BRAIN_DEATH
++    void  (*add_module) ();
++    void  (*remove_module) ();
++    char *(*rewrite_command) ();
++    void  (*new_connection) ();
++    void  (*close_connection) ();
++#else
++    void  (*add_module) (struct module_struct *);
++    void  (*remove_module) (struct module_struct *);
++    char *(*rewrite_command) (cmd_parms *, void *config, const char *);
++    void  (*new_connection) (conn_rec *);
++    void  (*close_connection) (conn_rec *);
++#endif
++#endif /* EAPI */
+ } module;
+ /* Initializer for the first few module slots, which are only
+diff -Nru apache_1.3.9/src/include/http_main.h apache_1.3.9.EAPI/src/include/http_main.h
+--- apache_1.3.9/src/include/http_main.h       Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/http_main.h  Wed Dec 29 21:25:56 1999
+@@ -124,7 +124,11 @@
+ API_EXPORT(void) ap_sync_scoreboard_image(void);
+ int ap_update_child_status(int child_num, int status, request_rec *r);
+ void ap_time_process_request(int child_num, int status);
++#ifdef EAPI
++API_EXPORT(unsigned int) ap_set_callback_and_alarm(void (*fn) (int), int x);
++#else
+ unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x);
++#endif
+ API_EXPORT(int) ap_check_alarm(void);
+ #ifndef NO_OTHER_CHILD
+diff -Nru apache_1.3.9/src/include/httpd.h apache_1.3.9.EAPI/src/include/httpd.h
+--- apache_1.3.9/src/include/httpd.h   Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/include/httpd.h      Wed Dec 29 21:25:56 1999
+@@ -69,7 +69,19 @@
+ /* Headers in which EVERYONE has an interest... */
+ #include "ap_config.h"
++#ifdef EAPI
++#include "ap_mm.h"
++#endif
+ #include "alloc.h"
++/*
++ * Include the Extended API headers.
++ * Don't move the position. It has to be after alloc.h because it uses the
++ * pool stuff but before buff.h because the buffer stuff uses the EAPI, too. 
++ */
++#ifdef EAPI
++#include "ap_hook.h"
++#include "ap_ctx.h"
++#endif /* EAPI */
+ #include "buff.h"
+ #include "ap.h"
+@@ -138,8 +150,13 @@
+ #define DEFAULT_HTTP_PORT     80
+ #define DEFAULT_HTTPS_PORT    443
+ #define ap_is_default_port(port,r)    ((port) == ap_default_port(r))
++#ifdef EAPI
++#define ap_http_method(r)   (ap_ctx_get((r)->ctx, "ap::http::method") != NULL ? ((char *)ap_ctx_get((r)->ctx, "ap::http::method")) : "http")
++#define ap_default_port(r)  (ap_ctx_get((r)->ctx, "ap::default::port") != NULL ? atoi((char *)ap_ctx_get((r)->ctx, "ap::default::port")) : DEFAULT_HTTP_PORT)
++#else /* EAPI */
+ #define ap_http_method(r)     "http"
+ #define ap_default_port(r)    DEFAULT_HTTP_PORT
++#endif /* EAPI */
+ /* --------- Default user name and group name running standalone ---------- */
+ /* --- These may be specified as numbers by placing a # before a number --- */
+@@ -351,6 +368,19 @@
+ #define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
+ #endif
++/*
++ * Unix only:
++ * Path to Shared Memory Files 
++ */
++#ifdef EAPI
++#ifndef EAPI_MM_CORE_PATH
++#define EAPI_MM_CORE_PATH "logs/mm"
++#endif
++#ifndef EAPI_MM_CORE_MAXSIZE
++#define EAPI_MM_CORE_MAXSIZE 1024*1024*1 /* max. 1MB */
++#endif
++#endif
++
+ /* Number of requests to try to handle in a single process.  If <= 0,
+  * the children don't die off.  That's the default here, since I'm still
+  * interested in finding and stanching leaks.
+@@ -430,6 +460,9 @@
+ API_EXPORT(const char *) ap_get_server_version(void);
+ API_EXPORT(void) ap_add_version_component(const char *component);
+ API_EXPORT(const char *) ap_get_server_built(void);
++#ifdef EAPI
++API_EXPORT(void) ap_add_config_define(const char *define);
++#endif /* EAPI */
+ /* Numeric release version identifier: MMNNFFRBB: major minor fix final beta
+  * Always increases along the same track as the source branch.
+@@ -801,6 +834,10 @@
+  * record to improve 64bit alignment the next time we need to break
+  * binary compatibility for some other reason.
+  */
++
++#ifdef EAPI
++    ap_ctx *ctx;
++#endif /* EAPI */
+ };
+@@ -849,6 +886,9 @@
+     char *local_host;         /* used for ap_get_server_name when
+                                * UseCanonicalName is set to DNS
+                                * (ignores setting of HostnameLookups) */
++#ifdef EAPI
++    ap_ctx *ctx;
++#endif /* EAPI */
+ };
+ /* Per-vhost config... */
+@@ -921,6 +961,10 @@
+     int limit_req_line;      /* limit on size of the HTTP request line    */
+     int limit_req_fieldsize; /* limit on size of any request header field */
+     int limit_req_fields;    /* limit on number of request header fields  */
++
++#ifdef EAPI
++    ap_ctx *ctx;
++#endif /* EAPI */
+ };
+ /* These are more like real hosts than virtual hosts */
+diff -Nru apache_1.3.9/src/main/alloc.c apache_1.3.9.EAPI/src/main/alloc.c
+--- apache_1.3.9/src/main/alloc.c      Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/main/alloc.c Wed Dec 29 21:25:56 1999
+@@ -63,6 +63,10 @@
+  */
+ #include "httpd.h"
++#ifdef EAPI
++#include "http_config.h"
++#include "http_conf_globals.h"
++#endif
+ #include "multithread.h"
+ #include "http_log.h"
+@@ -137,6 +141,10 @@
+ #define BLOCK_MINALLOC        0
+ #endif
++#if defined(EAPI) && defined(EAPI_MM)
++static AP_MM *mm = NULL;
++#endif
++
+ /*****************************************************************
+  *
+  * Managing free storage blocks...
+@@ -165,6 +173,9 @@
+       char *endp;
+       union block_hdr *next;
+       char *first_avail;
++#if defined(EAPI) && defined(EAPI_MM)
++      int is_shm;
++#endif
+ #ifdef POOL_DEBUG
+       union block_hdr *global_next;
+       struct pool *owning_pool;
+@@ -215,7 +226,11 @@
+ /* Get a completely new block from the system pool. Note that we rely on
+    malloc() to provide aligned memory. */
++#if defined(EAPI) && defined(EAPI_MM)
++static union block_hdr *malloc_block(int size, int is_shm)
++#else
+ static union block_hdr *malloc_block(int size)
++#endif
+ {
+     union block_hdr *blok;
+@@ -229,12 +244,20 @@
+     ++num_malloc_calls;
+     num_malloc_bytes += size + sizeof(union block_hdr);
+ #endif
++#if defined(EAPI) && defined(EAPI_MM)
++    if (is_shm)
++        blok = (union block_hdr *)ap_mm_malloc(mm, size + sizeof(union block_hdr));
++    else
++#endif
+     blok = (union block_hdr *) malloc(size + sizeof(union block_hdr));
+     if (blok == NULL) {
+       fprintf(stderr, "Ouch!  malloc failed in malloc_block()\n");
+       exit(1);
+     }
+     debug_fill(blok, size + sizeof(union block_hdr));
++#if defined(EAPI) && defined(EAPI_MM)
++    blok->h.is_shm = is_shm;
++#endif
+     blok->h.next = NULL;
+     blok->h.first_avail = (char *) (blok + 1);
+     blok->h.endp = size + blok->h.first_avail;
+@@ -295,6 +318,10 @@
+     if (blok == NULL)
+       return;                 /* Sanity check --- freeing empty pool? */
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm)
++        (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+     (void) ap_acquire_mutex(alloc_mutex);
+     old_free_list = block_freelist;
+     block_freelist = blok;
+@@ -341,6 +368,10 @@
+ #endif
+     (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm)
++        (void)ap_mm_unlock(mm);
++#endif
+ #endif
+ }
+@@ -349,7 +380,11 @@
+  * if necessary.  Must be called with alarms blocked.
+  */
++#if defined(EAPI) && defined(EAPI_MM)
++static union block_hdr *new_block(int min_size, int is_shm)
++#else
+ static union block_hdr *new_block(int min_size)
++#endif
+ {
+     union block_hdr **lastptr = &block_freelist;
+     union block_hdr *blok = block_freelist;
+@@ -359,7 +394,12 @@
+      */
+     while (blok != NULL) {
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm == is_shm &&
++        min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
++#else
+       if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
++#endif
+           *lastptr = blok->h.next;
+           blok->h.next = NULL;
+           debug_verify_filled(blok->h.first_avail, blok->h.endp,
+@@ -375,7 +415,11 @@
+     /* Nope. */
+     min_size += BLOCK_MINFREE;
++#if defined(EAPI) && defined(EAPI_MM)
++    blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC, is_shm);
++#else
+     blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC);
++#endif
+     return blok;
+ }
+@@ -425,6 +469,9 @@
+ #ifdef POOL_DEBUG
+     struct pool *joined;
+ #endif
++#if defined(EAPI) && defined(EAPI_MM)
++    int is_shm;
++#endif
+ };
+ static pool *permanent_pool;
+@@ -439,16 +486,28 @@
+ #define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ))
+ #define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
++#if defined(EAPI) && defined(EAPI_MM)
++static struct pool *make_sub_pool_internal(struct pool *p, int is_shm)
++#else
+ API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
++#endif
+ {
+     union block_hdr *blok;
+     pool *new_pool;
+     ap_block_alarms();
++#if defined(EAPI) && defined(EAPI_MM)
++    if (is_shm)
++        (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+     (void) ap_acquire_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    blok = new_block(POOL_HDR_BYTES, is_shm);
++#else
+     blok = new_block(POOL_HDR_BYTES);
++#endif
+     new_pool = (pool *) blok->h.first_avail;
+     blok->h.first_avail += POOL_HDR_BYTES;
+ #ifdef POOL_DEBUG
+@@ -467,12 +526,38 @@
+       p->sub_pools = new_pool;
+     }
++#if defined(EAPI) && defined(EAPI_MM)
++    new_pool->is_shm = is_shm;
++#endif
++
+     (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (is_shm)
++      (void)ap_mm_unlock(mm);
++#endif
+     ap_unblock_alarms();
+     return new_pool;
+ }
++#if defined(EAPI)
++#if defined(EAPI_MM)
++API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
++{
++    return make_sub_pool_internal(p, 0);
++}
++API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p)
++{
++    return make_sub_pool_internal(p, 1);
++}
++#else
++API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p)
++{
++    return NULL;
++}
++#endif
++#endif
++
+ #ifdef POOL_DEBUG
+ static void stack_var_init(char *s)
+ {
+@@ -487,6 +572,13 @@
+ }
+ #endif
++#if defined(EAPI)
++int ap_shared_pool_possible(void)
++{
++    return ap_mm_useable();
++}
++#endif
++
+ #ifdef ALLOC_STATS
+ static void dump_stats(void)
+ {
+@@ -519,14 +611,73 @@
+     return permanent_pool;
+ }
++#if defined(EAPI)
++void ap_init_alloc_shared(int early)
++{
++#if defined(EAPI_MM)
++    int mm_size;
++    char *mm_path;
++    char *err1, *err2;
++
++    if (early) {
++        /* process very early on startup */
++        mm_size = ap_mm_maxsize();
++        if (mm_size > EAPI_MM_CORE_MAXSIZE)
++            mm_size = EAPI_MM_CORE_MAXSIZE;
++        mm_path = ap_server_root_relative(permanent_pool, EAPI_MM_CORE_PATH);
++        if ((mm = ap_mm_create(mm_size, mm_path)) == NULL) {
++            fprintf(stderr, "Ouch! ap_mm_create(%d, \"%s\") failed\n", mm_size, mm_path);
++            err1 = ap_mm_error();
++            if (err1 == NULL)
++                err1 = "-unknown-";
++            err2 = strerror(errno);
++            if (err2 == NULL)
++                err2 = "-unknown-";
++            fprintf(stderr, "Error: MM: %s: OS: %s\n", err1, err2);
++            abort();
++            exit(1);
++        }
++    }
++    else {
++        /* process a lot later on startup */
++#ifdef WIN32
++        ap_mm_permission(mm, (_S_IREAD|_S_IWRITE), ap_user_id, -1);
++#else
++        ap_mm_permission(mm, (S_IRUSR|S_IWUSR), ap_user_id, -1);
++#endif
++    }
++#endif /* EAPI_MM */
++    return; 
++}
++
++void ap_kill_alloc_shared(void)
++{
++#if defined(EAPI_MM)
++    if (mm != NULL) {
++        ap_mm_destroy(mm);
++        mm = NULL;
++    }
++#endif /* EAPI_MM */
++    return;
++}
++#endif /* EAPI */
++
+ API_EXPORT(void) ap_clear_pool(struct pool *a)
+ {
+     ap_block_alarms();
++#if defined(EAPI) && defined(EAPI_MM)
++    if (a->is_shm)
++        (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+     (void) ap_acquire_mutex(alloc_mutex);
+     while (a->sub_pools)
+       ap_destroy_pool(a->sub_pools);
+     (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (a->is_shm)
++          (void)ap_mm_unlock(mm);
++#endif
+     /* Don't hold the mutex during cleanups. */
+     run_cleanups(a->cleanups);
+     a->cleanups = NULL;
+@@ -560,6 +711,10 @@
+     ap_block_alarms();
+     ap_clear_pool(a);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (a->is_shm)
++      (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+     (void) ap_acquire_mutex(alloc_mutex);
+     if (a->parent) {
+       if (a->parent->sub_pools == a)
+@@ -570,6 +725,10 @@
+           a->sub_next->sub_prev = a->sub_prev;
+     }
+     (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (a->is_shm)
++      (void)ap_mm_unlock(mm);
++#endif
+     free_blocks(a->first);
+     ap_unblock_alarms();
+@@ -584,6 +743,30 @@
+     return bytes_in_block_list(block_freelist);
+ }
++#if defined(EAPI)
++API_EXPORT(int) ap_acquire_pool(pool *p, ap_pool_lock_mode mode)
++{
++#if defined(EAPI_MM)
++    if (!p->is_shm)
++        return 1;
++    return ap_mm_lock(mm, mode == AP_POOL_RD ? AP_MM_LOCK_RD : AP_MM_LOCK_RW);
++#else
++      return 1;
++#endif
++}
++
++API_EXPORT(int) ap_release_pool(pool *p)
++{
++#if defined(EAPI_MM)
++    if (!p->is_shm)
++        return 1;
++    return ap_mm_unlock(mm);
++#else
++      return 1;
++#endif
++}
++#endif /* EAPI */
++
+ /*****************************************************************
+  * POOL_DEBUG support
+  */
+@@ -749,16 +932,31 @@
+     ap_block_alarms();
++#if defined(EAPI) && defined(EAPI_MM)
++    if (a->is_shm)
++      (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+     (void) ap_acquire_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    blok = new_block(size, a->is_shm);
++#else
+     blok = new_block(size);
++#endif
+     a->last->h.next = blok;
+     a->last = blok;
+ #ifdef POOL_DEBUG
+     blok->h.owning_pool = a;
+ #endif
++#if defined(EAPI) && defined(EAPI_MM)
++    blok->h.is_shm = a->is_shm;
++#endif
+     (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (a->is_shm)
++      (void)ap_mm_unlock(mm);
++#endif
+     ap_unblock_alarms();
+@@ -870,6 +1068,11 @@
+     char *ptr;
+     size = (char *)ps->vbuff.curpos - ps->base;
++#if defined(EAPI) && defined(EAPI_MM)
++    if (ps->block->h.is_shm)
++        ptr = ap_mm_realloc(ps->base, 2*size);
++    else
++#endif
+     ptr = realloc(ps->base, 2*size);
+     if (ptr == NULL) {
+       fputs("Ouch!  Out of memory!\n", stderr);
+@@ -890,9 +1093,21 @@
+     cur_len = strp - blok->h.first_avail;
+     /* must try another blok */
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm)
++      (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+     (void) ap_acquire_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    nblok = new_block(2 * cur_len, blok->h.is_shm);
++#else
+     nblok = new_block(2 * cur_len);
++#endif
+     (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm)
++      (void)ap_mm_unlock(mm);
++#endif
+     memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
+     ps->vbuff.curpos = nblok->h.first_avail + cur_len;
+     /* save a byte for the NUL terminator */
+@@ -901,10 +1116,18 @@
+     /* did we allocate the current blok? if so free it up */
+     if (ps->got_a_new_block) {
+       debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm)
++      (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
++#endif
+       (void) ap_acquire_mutex(alloc_mutex);
+       blok->h.next = block_freelist;
+       block_freelist = blok;
+       (void) ap_release_mutex(alloc_mutex);
++#if defined(EAPI) && defined(EAPI_MM)
++    if (blok->h.is_shm)
++      (void)ap_mm_unlock(mm);
++#endif
+     }
+     ps->blok = nblok;
+     ps->got_a_new_block = 1;
+@@ -923,6 +1146,11 @@
+     void *ptr;
+     ap_block_alarms();
++#if defined(EAPI) && defined(EAPI_MM)
++    if (p->is_shm)
++        ps.base = ap_mm_malloc(mm, 512);
++    else
++#endif
+     ps.base = malloc(512);
+     if (ps.base == NULL) {
+       fputs("Ouch!  Out of memory!\n", stderr);
+@@ -935,6 +1163,11 @@
+     *ps.vbuff.curpos++ = '\0';
+     ptr = ps.base;
+     /* shrink */
++#if defined(EAPI) && defined(EAPI_MM)
++    if (p->is_shm)
++        ptr = ap_mm_realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
++    else
++#endif
+     ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
+     if (ptr == NULL) {
+       fputs("Ouch!  Out of memory!\n", stderr);
+diff -Nru apache_1.3.9/src/main/buff.c apache_1.3.9.EAPI/src/main/buff.c
+--- apache_1.3.9/src/main/buff.c       Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/main/buff.c  Wed Dec 29 21:25:56 1999
+@@ -125,7 +125,11 @@
+   select() sometimes returns 1 even though the write will block. We must work around this.
+ */
++#ifdef EAPI
++API_EXPORT(int) sendwithtimeout(int sock, const char *buf, int len, int flags)
++#else /* EAPI */
+ int sendwithtimeout(int sock, const char *buf, int len, int flags)
++#endif /* EAPI */
+ {
+     int iostate = 1;
+     fd_set fdset;
+@@ -183,8 +187,11 @@
+     return (rv);
+ }
+-
++#ifdef EAPI
++API_EXPORT(int) recvwithtimeout(int sock, char *buf, int len, int flags)
++#else /* EAPI */
+ int recvwithtimeout(int sock, char *buf, int len, int flags)
++#endif /* EAPI */
+ {
+     int iostate = 1;
+     fd_set fdset;
+@@ -242,6 +249,9 @@
+     }
+     else
+ #endif
++#ifdef EAPI
++      if (!ap_hook_call("ap::buff::read", &rv, fb, buf, nbyte))
++#endif /* EAPI */
+       rv = read(fb->fd_in, buf, nbyte);
+     
+     return rv;
+@@ -253,6 +263,9 @@
+ #if defined (WIN32)
+     if (fb->flags & B_SOCKET) {
++#ifdef EAPI
++      if (!ap_hook_call("ap::buff::recvwithtimeout", &rv, fb, buf, nbyte))
++#endif /* EAPI */
+       rv = recvwithtimeout(fb->fd_in, buf, nbyte, 0);
+       if (rv == SOCKET_ERROR)
+           errno = WSAGetLastError();
+@@ -299,6 +312,9 @@
+     }
+     else
+ #endif
++#ifdef EAPI
++      if (!ap_hook_call("ap::buff::write", &rv, fb, buf, nbyte))
++#endif /* EAPI */
+ #if defined (B_SFIO)
+       rv = sfwrite(fb->sf_out, buf, nbyte);
+ #else
+@@ -314,6 +330,9 @@
+ #if defined(WIN32)
+     if (fb->flags & B_SOCKET) {
++#ifdef EAPI
++      if (!ap_hook_call("ap::buff::sendwithtimeout", &rv, fb, buf, nbyte))
++#endif /* EAPI */
+       rv = sendwithtimeout(fb->fd, buf, nbyte, 0);
+       if (rv == SOCKET_ERROR)
+           errno = WSAGetLastError();
+@@ -394,6 +413,10 @@
+                      (size_t) SF_UNBOUND, 1, SF_WRITE);
+ #endif
++#ifdef EAPI
++    fb->ctx = ap_ctx_new(p);
++#endif /* EAPI */
++
+     return fb;
+ }
+@@ -1051,6 +1074,9 @@
+     i = 0;
+     while (i < nvec) {
+       do
++#ifdef EAPI
++          if (!ap_hook_call("ap::buff::writev", &rv, fb, &vec[i], nvec -i))
++#endif /* EAPI */
+           rv = writev(fb->fd, &vec[i], nvec - i);
+       while (rv == -1 && (errno == EINTR || errno == EAGAIN)
+              && !(fb->flags & B_EOUT));
+diff -Nru apache_1.3.9/src/main/http_config.c apache_1.3.9.EAPI/src/main/http_config.c
+--- apache_1.3.9/src/main/http_config.c        Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/main/http_config.c   Wed Dec 29 21:25:56 1999
+@@ -583,6 +583,20 @@
+       m->name = tmp;
+     }
+ #endif /*_OSD_POSIX*/
++
++#ifdef EAPI
++    /*
++     * Invoke the `add_module' hook inside the now existing set
++     * of modules to let them all now that this module was added.
++     */
++    {
++        module *m2;
++        for (m2 = top_module; m2 != NULL; m2 = m2->next)
++            if (m2->magic == MODULE_MAGIC_COOKIE_EAPI)
++                if (m2->add_module != NULL)
++                    (*m2->add_module)(m);
++    }
++#endif /* EAPI */
+ }
+ /* 
+@@ -597,6 +611,21 @@
+ {
+     module *modp;
++#ifdef EAPI
++    /*
++     * Invoke the `remove_module' hook inside the now existing
++     * set of modules to let them all now that this module is
++     * beeing removed.
++     */
++    {
++        module *m2;
++        for (m2 = top_module; m2 != NULL; m2 = m2->next)
++            if (m2->magic == MODULE_MAGIC_COOKIE_EAPI)
++                if (m2->remove_module != NULL)
++                    (*m2->remove_module)(m);
++    }
++#endif /* EAPI */
++
+     modp = top_module;
+     if (modp == m) {
+       /* We are the top module, special case */
+@@ -985,6 +1014,27 @@
+     const command_rec *cmd;
+     module *mod = top_module;
++#ifdef EAPI
++    /*
++     * Invoke the `rewrite_command' of modules to allow
++     * they to rewrite the directive line before we
++     * process it.
++     */
++    {
++        module *m;
++        char *cp;
++        for (m = top_module; m != NULL; m = m->next) {
++            if (m->magic == MODULE_MAGIC_COOKIE_EAPI) {
++                if (m->rewrite_command != NULL) {
++                    cp = (m->rewrite_command)(parms, config, l);
++                    if (cp != NULL)
++                        l = cp;
++                }
++            }
++        }
++    }
++#endif /* EAPI */
++
+     if ((l[0] == '#') || (!l[0]))
+       return NULL;
+@@ -1334,6 +1384,10 @@
+     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
+     s->limit_req_fields = main_server->limit_req_fields;
++#ifdef EAPI
++    s->ctx = ap_ctx_new(p);
++#endif /* EAPI */
++
+     *ps = s;
+     return ap_parse_vhost_addrs(p, hostname, s);
+@@ -1483,6 +1537,10 @@
+     s->module_config = create_server_config(p, s);
+     s->lookup_defaults = create_default_per_dir_config(p);
++
++#ifdef EAPI
++    s->ctx = ap_ctx_new(p);
++#endif /* EAPI */
+     return s;
+ }
+diff -Nru apache_1.3.9/src/main/http_main.c apache_1.3.9.EAPI/src/main/http_main.c
+--- apache_1.3.9/src/main/http_main.c  Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/main/http_main.c     Wed Dec 29 21:25:56 1999
+@@ -256,6 +256,9 @@
+ int ap_listenbacklog;
+ int ap_dump_settings = 0;
+ API_VAR_EXPORT int ap_extended_status = 0;
++#ifdef EAPI
++API_VAR_EXPORT ap_ctx *ap_global_ctx;
++#endif /* EAPI */
+ /*
+  * The max child slot ever assigned, preserved across restarts.  Necessary
+@@ -427,6 +430,30 @@
+     }
+ }
++#ifdef EAPI
++API_EXPORT(void) ap_add_config_define(const char *define)
++{
++    char **var;
++    var = (char **)ap_push_array(ap_server_config_defines);
++    *var = ap_pstrdup(pcommands, define);
++    return;
++}
++
++/*
++ * Invoke the `close_connection' hook of modules to let them do
++ * some connection dependent actions before we close it.
++ */
++static void ap_call_close_connection_hook(conn_rec *c)
++{
++    module *m;
++    for (m = top_module; m != NULL; m = m->next)
++        if (m->magic == MODULE_MAGIC_COOKIE_EAPI)
++            if (m->close_connection != NULL)
++                (*m->close_connection)(c);
++    return;
++}
++#endif /* EAPI */
++
+ static APACHE_TLS int volatile exit_after_unblock = 0;
+ #ifdef GPROF
+@@ -1144,6 +1171,10 @@
+           ap_log_transaction(log_req);
+       }
++#ifdef EAPI
++      ap_call_close_connection_hook(save_req->connection);
++#endif /* EAPI */
++
+       ap_bsetflag(save_req->connection->client, B_EOUT, 1);
+       ap_bclose(save_req->connection->client);
+@@ -1153,6 +1184,9 @@
+       ap_longjmp(jmpbuffer, 1);
+     }
+     else {                    /* abort the connection */
++#ifdef EAPI
++      ap_call_close_connection_hook(current_conn);
++#endif /* EAPI */
+       ap_bsetflag(current_conn->client, B_EOUT, 1);
+       ap_bclose(current_conn->client);
+       current_conn->aborted = 1;
+@@ -1209,7 +1243,11 @@
+ }
+ #endif
++#ifdef EAPI
++API_EXPORT(unsigned int) ap_set_callback_and_alarm(void (*fn) (int), int x)
++#else
+ unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x)
++#endif
+ {
+     unsigned int old;
+@@ -1426,10 +1464,16 @@
+     /* Send any leftover data to the client, but never try to again */
+     if (ap_bflush(r->connection->client) == -1) {
++#ifdef EAPI
++      ap_call_close_connection_hook(r->connection);
++#endif /* EAPI */
+       ap_kill_timeout(r);
+       ap_bclose(r->connection->client);
+       return;
+     }
++#ifdef EAPI
++    ap_call_close_connection_hook(r->connection);
++#endif /* EAPI */
+     ap_bsetflag(r->connection->client, B_EOUT, 1);
+     /* Close our half of the connection --- send the client a FIN */
+@@ -2121,6 +2165,9 @@
+ {
+     /* Clear the pool - including any registered cleanups */
+     ap_destroy_pool(pglobal);
++#ifdef EAPI
++    ap_kill_alloc_shared();
++#endif
+     exit(code);
+ }
+@@ -3105,6 +3152,25 @@
+     hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
+     conn->remote_ip = ap_pstrdup(conn->pool, hostnamebuf);
++#ifdef EAPI
++    conn->ctx = ap_ctx_new(conn->pool);
++#endif /* EAPI */
++  
++#ifdef EAPI
++    /*
++     * Invoke the `new_connection' hook of modules to let them do
++     * some connection dependent actions before we go on with
++     * processing the request on this connection.
++     */
++    {
++        module *m;
++        for (m = top_module; m != NULL; m = m->next)
++            if (m->magic == MODULE_MAGIC_COOKIE_EAPI)
++                if (m->new_connection != NULL)
++                    (*m->new_connection)(conn);
++    }
++#endif /* EAPI */
++
+     return conn;
+ }
+@@ -3541,6 +3607,12 @@
+     printf("Server's Module Magic Number: %u:%u\n",
+          MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
+     printf("Server compiled with....\n");
++#ifdef EAPI
++    printf(" -D EAPI\n");
++#endif
++#ifdef EAPI_MM
++    printf(" -D EAPI_MM\n");
++#endif
+ #ifdef BIG_SECURITY_HOLE
+     printf(" -D BIG_SECURITY_HOLE\n");
+ #endif
+@@ -3688,6 +3760,22 @@
+     ap_server_pre_read_config  = ap_make_array(pcommands, 1, sizeof(char *));
+     ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *));
+     ap_server_config_defines   = ap_make_array(pcommands, 1, sizeof(char *));
++
++#ifdef EAPI
++    ap_hook_init();
++    ap_hook_configure("ap::buff::read", 
++                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
++    ap_hook_configure("ap::buff::write",  
++                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
++    ap_hook_configure("ap::buff::writev",  
++                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
++    ap_hook_configure("ap::buff::sendwithtimeout", 
++                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
++    ap_hook_configure("ap::buff::recvwithtimeout", 
++                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
++
++    ap_global_ctx = ap_ctx_new(NULL);
++#endif /* EAPI */
+ }
+ #ifndef MULTITHREAD
+@@ -4109,6 +4197,9 @@
+           ap_sync_scoreboard_image();
+           if (ap_scoreboard_image->global.running_generation != ap_my_generation) {
++#ifdef EAPI
++              ap_call_close_connection_hook(current_conn);
++#endif /* EAPI */
+               ap_bclose(conn_io);
+               clean_child_exit(0);
+           }
+@@ -4137,6 +4228,9 @@
+        */
+ #ifdef NO_LINGCLOSE
++#ifdef EAPI
++      ap_call_close_connection_hook(current_conn);
++#endif /* EAPI */
+       ap_bclose(conn_io);     /* just close it */
+ #else
+       if (r && r->connection
+@@ -4147,6 +4241,9 @@
+           lingering_close(r);
+       }
+       else {
++#ifdef EAPI
++          ap_call_close_connection_hook(current_conn);
++#endif /* EAPI */
+           ap_bsetflag(conn_io, B_EOUT, 1);
+           ap_bclose(conn_io);
+       }
+@@ -4879,10 +4976,17 @@
+           usage(argv[0]);
+       }
+     }
++#ifdef EAPI
++    ap_init_alloc_shared(TRUE);
++#endif
+     ap_suexec_enabled = init_suexec();
+     server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
++#ifdef EAPI
++    ap_init_alloc_shared(FALSE);
++#endif
++
+     if (ap_configtestonly) {
+         fprintf(stderr, "Syntax OK\n");
+         exit(0);
+@@ -5033,6 +5137,10 @@
+           ap_destroy_pool(r->pool);
+       }
++#ifdef EAPI
++      ap_call_close_connection_hook(conn);
++#endif /* EAPI */
++
+       ap_bclose(cio);
+     }
+     exit(0);
+@@ -5361,6 +5469,9 @@
+       ap_kill_cleanups_for_socket(ptrans, csd);
+ #ifdef NO_LINGCLOSE
++#ifdef EAPI
++      ap_call_close_connection_hook(current_conn);
++#endif /* EAPI */
+       ap_bclose(conn_io);     /* just close it */
+ #else
+       if (r && r->connection
+@@ -5371,6 +5482,9 @@
+           lingering_close(r);
+       }
+       else {
++#ifdef EAPI
++          ap_call_close_connection_hook(current_conn);
++#endif /* EAPI */
+           ap_bsetflag(conn_io, B_EOUT, 1);
+           ap_bclose(conn_io);
+       }
+@@ -6490,6 +6604,10 @@
+         }
+     }
++#ifdef EAPI
++    ap_init_alloc_shared(TRUE);
++#endif
++
+     if (!ap_os_is_path_absolute(ap_server_confname)) {
+         char *full_conf_path;
+@@ -6522,6 +6640,10 @@
+     }
+ #endif
+     server_conf = ap_read_config(pconf, ptrans, ap_server_confname);
++
++#ifdef EAPI
++    ap_init_alloc_shared(FALSE);
++#endif
+     if (ap_configtestonly) {
+         fprintf(stderr, "%s: Syntax OK\n", ap_server_root_relative(pcommands, ap_server_confname));
+diff -Nru apache_1.3.9/src/main/http_protocol.c apache_1.3.9.EAPI/src/main/http_protocol.c
+--- apache_1.3.9/src/main/http_protocol.c      Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/main/http_protocol.c Wed Dec 29 21:25:56 1999
+@@ -935,6 +935,10 @@
+     r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
+     r->the_request     = NULL;
++#ifdef EAPI
++    r->ctx = ap_ctx_new(r->pool);
++#endif /* EAPI */
++
+ #ifdef CHARSET_EBCDIC
+     ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1);
+ #endif
+@@ -1079,6 +1083,11 @@
+     rnew->read_body       = REQUEST_NO_BODY;
+     rnew->main = (request_rec *) r;
++
++#ifdef EAPI
++    rnew->ctx = r->ctx;
++#endif /* EAPI */
++
+ }
+ void ap_finalize_sub_req_protocol(request_rec *sub)
+diff -Nru apache_1.3.9/src/main/http_request.c apache_1.3.9.EAPI/src/main/http_request.c
+--- apache_1.3.9/src/main/http_request.c       Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/main/http_request.c  Wed Dec 29 21:25:56 1999
+@@ -1315,6 +1315,9 @@
+     new->no_local_copy   = r->no_local_copy;
+     new->read_length     = r->read_length;     /* We can only read it once */
+     new->vlist_validator = r->vlist_validator;
++#ifdef EAPI
++    new->ctx             = r->ctx;
++#endif /* EAPI */
+     ap_table_setn(new->subprocess_env, "REDIRECT_STATUS",
+       ap_psprintf(r->pool, "%d", r->status));
+diff -Nru apache_1.3.9/src/modules/extra/mod_define.c apache_1.3.9.EAPI/src/modules/extra/mod_define.c
+--- apache_1.3.9/src/modules/extra/mod_define.c        Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/modules/extra/mod_define.c   Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,446 @@
++/* ====================================================================
++ * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ *
++ */
++
++/*
++**  mod_define.c -- Apache module for configuration defines ($xxx)
++**  v1.0: Originally written in December 1998 by 
++**        Ralf S. Engelschall <rse@engelschall.com> and
++**        Christian Reiber <chrei@en.muc.de>
++**  v1.1: Completely Overhauled in August 1999 by
++**        Ralf S. Engelschall <rse@engelschall.com>
++*/
++
++#include "ap_config.h"
++#include "ap_ctype.h"
++#include "httpd.h"
++#include "http_config.h"
++#include "http_conf_globals.h"
++#include "http_core.h"
++#include "http_log.h"
++
++#ifndef EAPI
++#error "This module requires the Extended API (EAPI) facilities."
++#endif
++
++/* 
++ * The global table of defines
++ */
++
++static table *tDefines         = NULL;   /* global table of defines */
++static int    bOnceSeenADefine = FALSE;  /* optimization flag */
++
++/* 
++ * Forward declaration
++ */
++static int   DefineIndex      (pool *, char *, int *, int *, char **);
++static char *DefineFetch      (pool *, char *);
++static char *DefineExpand     (pool *, char *, int, char *);
++static void  DefineInit       (pool *);
++static void  DefineCleanup    (void *);
++static char *DefineRewriteHook(cmd_parms *, void *, const char *);
++
++/*
++ * Character classes for scanner function
++ */
++typedef enum {
++    CC_ESCAPE, CC_DOLLAR, CC_BRACEOPEN, CC_BRACECLOSE, 
++    CC_IDCHAR1, CC_IDCHAR, CC_OTHER, CC_EOS   
++} CharClass;
++
++/*
++ * Scanner states for scanner function
++ */
++typedef enum {
++    SS_NONE, SS_SKIP, SS_DOLLAR, SS_TOKEN_BRACED,
++    SS_TOKEN_UNBRACED, SS_ERROR, SS_FOUND
++} ScanState;
++
++/*
++ * Default meta characters
++ */
++#define DEFAULT_MC_ESCAPE      "\\"
++#define DEFAULT_MC_DOLLAR      "$"
++#define DEFAULT_MC_BRACEOPEN   "{"
++#define DEFAULT_MC_BRACECLOSE  "}"
++
++/*
++ * Scanner for variable constructs $xxx and ${xxx}
++ */
++static int DefineIndex(pool *p, char *cpLine, int *pos, int *len, char **cpVar)
++{
++    int rc;
++    char *cp;
++    char *cp2;
++    CharClass cc;
++    char cEscape;
++    char cDefine;
++    char cBraceOpen;
++    char cBraceClose;
++    char *cpError;
++    ScanState s;
++
++    cEscape = DEFAULT_MC_ESCAPE[0];
++    if ((cp = DefineFetch(p, "mod_define::escape")) != NULL)
++        cEscape = cp[0];
++    cDefine = DEFAULT_MC_DOLLAR[0];
++    if ((cp = DefineFetch(p, "mod_define::dollar")) != NULL)
++        cDefine = cp[0];
++    cBraceOpen = DEFAULT_MC_BRACEOPEN[0];
++    if ((cp = DefineFetch(p, "mod_define::braceopen")) != NULL)
++        cBraceOpen = cp[0];
++    cBraceClose = DEFAULT_MC_BRACECLOSE[0];
++    if ((cp = DefineFetch(p, "mod_define::braceclose")) != NULL)
++        cBraceClose = cp[0];
++
++    rc = 0;
++    *len = 0;
++    cc = CC_OTHER;
++    s = SS_NONE;
++    for (cp = cpLine+(*pos); cc != CC_EOS; cp++) {
++        if (*cp == cEscape)
++            cc = CC_ESCAPE;
++        else if (*cp == cDefine)
++            cc = CC_DOLLAR;
++        else if (*cp == cBraceOpen)
++            cc = CC_BRACEOPEN;
++        else if (*cp == cBraceClose)
++            cc = CC_BRACECLOSE;
++        else if (ap_isalpha(*cp))
++            cc = CC_IDCHAR1;
++        else if (ap_isdigit(*cp) || *cp == '_' || *cp == ':')
++            cc = CC_IDCHAR;
++        else if (*cp == '\0')
++            cc = CC_EOS;
++        else
++            cc = CC_OTHER;
++        switch (s) {
++            case SS_NONE:
++                switch (cc) {
++                    case CC_ESCAPE: 
++                        s = SS_SKIP;
++                        break;
++                    case CC_DOLLAR: 
++                        s = SS_DOLLAR; 
++                        break;
++                    default:
++                        break;
++                }
++                break;
++            case SS_SKIP:
++                s = SS_NONE;
++                continue;
++                break;
++            case SS_DOLLAR:
++                switch (cc) {
++                    case CC_BRACEOPEN: 
++                        s = SS_TOKEN_BRACED;   
++                        *pos = cp-cpLine-1; 
++                        (*len) = 2; 
++                        *cpVar = cp+1; 
++                        break;
++                    case CC_IDCHAR1: 
++                        s = SS_TOKEN_UNBRACED; 
++                        *pos = cp-cpLine-1; 
++                        (*len) = 2; 
++                        *cpVar = cp; 
++                        break;
++                    case CC_ESCAPE:
++                        s = SS_SKIP; 
++                        break;
++                    default: 
++                        s = SS_NONE; 
++                        break;
++                }
++                break;
++            case SS_TOKEN_BRACED:
++                switch (cc) {
++                    case CC_IDCHAR1:
++                    case CC_IDCHAR: 
++                        (*len)++; 
++                        break;
++                    case CC_BRACECLOSE: 
++                        (*len)++; 
++                        cp2 = ap_palloc(p, cp-*cpVar+1);
++                        ap_cpystrn(cp2, *cpVar, cp-*cpVar+1); 
++                        *cpVar = cp2;
++                        s = SS_FOUND; 
++                        break;
++                    default:
++                        cpError = ap_psprintf(p, "Illegal character '%c' in identifier", *cp);
++                        s = SS_ERROR;
++                        break;
++                }
++                break;
++            case SS_TOKEN_UNBRACED:
++                switch (cc) {
++                    case CC_IDCHAR1:
++                    case CC_IDCHAR: 
++                        (*len)++; 
++                        break;
++                    default:
++                        cp2 = ap_palloc(p, cp-*cpVar+1);
++                        ap_cpystrn(cp2, *cpVar, cp-*cpVar+1); 
++                        *cpVar = cp2;
++                        s = SS_FOUND; 
++                        break;
++                }
++                break;
++            case SS_FOUND:
++            case SS_ERROR:
++                break;
++        }
++        if (s == SS_ERROR) {
++            fprintf(stderr, "Error\n");
++            break;
++        }
++        else if (s == SS_FOUND) {
++            rc = 1;
++            break;
++        }
++    }
++    return rc;
++}
++
++/*
++ * Determine the value of a variable
++ */
++static char *DefineFetch(pool *p, char *cpVar)
++{
++    char *cpVal;
++
++    /* first try out table */
++    if ((cpVal = (char *)ap_table_get(tDefines, (char *)cpVar)) != NULL)
++        return cpVal;
++    /* second try the environment */
++    if ((cpVal = getenv(cpVar)) != NULL)
++        return cpVal;
++    return NULL;
++}
++
++/*
++ * Expand a variable
++ */
++static char *DefineExpand(pool *p, char *cpToken, int tok_len, char *cpVal)
++{
++    char *cp;
++    int val_len, rest_len;
++
++    val_len  = strlen(cpVal);
++    rest_len = strlen(cpToken+tok_len);
++    if (val_len < tok_len) 
++        memcpy(cpToken+val_len, cpToken+tok_len, rest_len+1);
++    else if (val_len > tok_len)
++        for (cp = cpToken+strlen(cpToken); cp > cpToken+tok_len-1; cp--)  
++            *(cp+(val_len-tok_len)) = *cp;
++    memcpy(cpToken, cpVal, val_len);
++    return NULL;
++}
++
++/*
++ * The EAPI hook which is called after Apache has read a
++ * configuration line and before it's actually processed
++ */
++static char *DefineRewriteHook(cmd_parms *cmd, void *config, const char *line)
++{
++    pool *p;
++    char *cpBuf;
++    char *cpLine;
++    int pos;
++    int len;
++    char *cpError;
++    char *cpVar;
++    char *cpVal;
++    server_rec *s;
++
++    /* runtime optimization */
++    if (!bOnceSeenADefine)
++        return NULL;
++
++    p  = cmd->pool;
++    s  = cmd->server;
++
++    /*
++     * Search for:
++     *  ....\$[a-zA-Z][:_a-zA-Z0-9]*....
++     *  ....\${[a-zA-Z][:_a-zA-Z0-9]*}....
++     */
++    cpBuf = NULL;
++    cpLine = (char *)line;
++    pos = 0;
++    while (DefineIndex(p, cpLine, &pos, &len, &cpVar)) {
++#ifdef DEFINE_DEBUG
++        {
++        char prefix[1024];
++        char marker[1024];
++        int i;
++        for (i = 0; i < pos; i++)
++            prefix[i] = ' ';
++        prefix[i] = '\0';
++        for (i = 0; i < len; i++)
++            marker[i] = '^';
++        marker[i] = '\0';
++        fprintf(stderr, 
++                "Found variable `%s' (pos: %d, len: %d)\n"
++                "  %s\n"
++                "  %s%s\n",
++                cpVar, pos, len, cpLine, prefix, marker);
++        }
++#endif
++        if (cpBuf == NULL) {
++            cpBuf = ap_palloc(p, MAX_STRING_LEN);
++            ap_cpystrn(cpBuf, line, MAX_STRING_LEN);
++            cpLine = cpBuf;
++        }
++        if ((cpVal = DefineFetch(p, cpVar)) == NULL) {
++            ap_log_error(APLOG_MARK, APLOG_ERR, s, 
++                         "mod_define: Variable '%s' not defined: file %s, line %d", 
++                         cpVar, cmd->config_file->name,
++                         cmd->config_file->line_number);
++            cpBuf = NULL;
++            break;
++        }
++        if ((cpError = DefineExpand(p, cpLine+pos, len, cpVal)) != NULL) {
++            ap_log_error(APLOG_MARK, APLOG_ERR, s, 
++                         "mod_define: %s: file %s, line %d", 
++                         cpError, cmd->config_file->name,
++                         cmd->config_file->line_number);
++            cpBuf = NULL;
++            break;
++        }
++    }
++    return cpBuf;
++}
++
++/*
++ * Implementation of the `Define' configuration directive
++ */
++static const char *cmd_define(cmd_parms *cmd, void *config, 
++                              char *cpVar, char *cpVal)
++{
++    if (tDefines == NULL)
++        DefineInit(cmd->pool);
++    ap_table_set(tDefines, cpVar, cpVal);
++    bOnceSeenADefine = TRUE;
++    return NULL;
++}
++
++/*
++ * Module Initialization
++ */
++
++static void DefineInit(pool *p)
++{
++    tDefines = ap_make_table(p, 10);
++    /* predefine delimiters */
++    ap_table_set(tDefines, "mod_define::escape", DEFAULT_MC_ESCAPE);
++    ap_table_set(tDefines, "mod_define::dollar", DEFAULT_MC_DOLLAR);
++    ap_table_set(tDefines, "mod_define::open",   DEFAULT_MC_BRACEOPEN);
++    ap_table_set(tDefines, "mod_define::close",  DEFAULT_MC_BRACECLOSE);
++    ap_register_cleanup(p, NULL, DefineCleanup, ap_null_cleanup);
++    return;
++}
++
++/*
++ * Module Cleanup
++ */
++
++static void DefineCleanup(void *data)
++{
++    /* reset private variables when config pool is cleared */
++    tDefines         = NULL;
++    bOnceSeenADefine = FALSE;
++    return;
++}
++
++/* 
++ * Module Directive lists
++ */
++static const command_rec DefineDirectives[] = {
++    { "Define", cmd_define, NULL, RSRC_CONF|ACCESS_CONF, TAKE2,
++      "Define a configuration variable" },
++    { NULL }
++};
++
++/* 
++ * Module API dispatch list
++ */
++module MODULE_VAR_EXPORT define_module = {
++    STANDARD_MODULE_STUFF, 
++    NULL,                  /* module initializer                  */
++    NULL,                  /* create per-dir    config structures */
++    NULL,                  /* merge  per-dir    config structures */
++    NULL,                  /* create per-server config structures */
++    NULL,                  /* merge  per-server config structures */
++    DefineDirectives,      /* table of config file commands       */
++    NULL,                  /* [#8] MIME-typed-dispatched handlers */
++    NULL,                  /* [#1] URI to filename translation    */
++    NULL,                  /* [#4] validate user id from request  */
++    NULL,                  /* [#5] check if the user is ok _here_ */
++    NULL,                  /* [#2] check access by host address   */
++    NULL,                  /* [#6] determine MIME type            */
++    NULL,                  /* [#7] pre-run fixups                 */
++    NULL,                  /* [#9] log a transaction              */
++    NULL,                  /* [#3] header parser                  */
++    NULL,                  /* child_init                          */
++    NULL,                  /* child_exit                          */
++    NULL,                  /* [#0] post read-request              */
++    NULL,                  /* EAPI: add_module                    */
++    NULL,                  /* EAPI: del_module                    */
++    DefineRewriteHook,     /* EAPI: rewrite_command               */
++    NULL                   /* EAPI: new_connection                */
++};
++
+diff -Nru apache_1.3.9/src/modules/proxy/mod_proxy.c apache_1.3.9.EAPI/src/modules/proxy/mod_proxy.c
+--- apache_1.3.9/src/modules/proxy/mod_proxy.c Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/modules/proxy/mod_proxy.c    Wed Dec 29 21:25:56 1999
+@@ -214,6 +214,9 @@
+ static int proxy_fixup(request_rec *r)
+ {
+     char *url, *p;
++#ifdef EAPI
++    int rc;
++#endif /* EAPI */
+     if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0)
+       return DECLINED;
+@@ -221,6 +224,14 @@
+     url = &r->filename[6];
+ /* canonicalise each specific scheme */
++#ifdef EAPI
++    if (ap_hook_use("ap::mod_proxy::canon",
++                    AP_HOOK_SIG3(int,ptr,ptr),
++                    AP_HOOK_DECLINE(DECLINED),
++                    &rc, r, url) && rc != DECLINED)
++        return rc;  
++    else
++#endif /* EAPI */
+     if (strncasecmp(url, "http:", 5) == 0)
+       return ap_proxy_http_canon(r, url + 5, "http", DEFAULT_HTTP_PORT);
+     else if (strncasecmp(url, "ftp:", 4) == 0)
+@@ -238,7 +249,38 @@
+     ap_proxy_garbage_init(r, p);
+ }
+-
++#ifdef EAPI
++static void proxy_addmod(module *m)
++{
++    /* export: ap_proxy_http_canon() as `ap::mod_proxy::http::canon' */
++    ap_hook_configure("ap::mod_proxy::http::canon", 
++                      AP_HOOK_SIG5(int,ptr,ptr,ptr,int), AP_HOOK_TOPMOST);
++    ap_hook_register("ap::mod_proxy::http::canon", 
++                     ap_proxy_http_canon, AP_HOOK_NOCTX);
++
++    /* export: ap_proxy_http_handler() as `ap::mod_proxy::http::handler' */
++    ap_hook_configure("ap::mod_proxy::http::handler", 
++                      AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,int), AP_HOOK_TOPMOST);
++    ap_hook_register("ap::mod_proxy::http::handler", 
++                     ap_proxy_http_handler, AP_HOOK_NOCTX);
++
++    /* export: ap_proxyerror() as `ap::mod_proxy::error' */
++    ap_hook_configure("ap::mod_proxy::error", 
++                      AP_HOOK_SIG3(int,ptr,ptr), AP_HOOK_TOPMOST);
++    ap_hook_register("ap::mod_proxy::error", 
++                     ap_proxyerror, AP_HOOK_NOCTX);
++    return;
++}
++
++static void proxy_remmod(module *m)
++{
++      /* remove the hook references */
++    ap_hook_unregister("ap::mod_proxy::http::canon", ap_proxy_http_canon);
++    ap_hook_unregister("ap::mod_proxy::http::handler", ap_proxy_http_handler);
++    ap_hook_unregister("ap::mod_proxy::error", ap_proxyerror);
++    return;
++}
++#endif /* EAPI */
+ /* Send a redirection if the request contains a hostname which is not */
+ /* fully qualified, i.e. doesn't have a domain name appended. Some proxy */
+@@ -368,6 +410,14 @@
+               /* CONNECT is a special method that bypasses the normal
+                * proxy code.
+                */
++#ifdef EAPI
++              if (!ap_hook_use("ap::mod_proxy::handler",
++                               AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr),
++                               AP_HOOK_DECLINE(DECLINED),
++                               &rc, r, cr, url, 
++                               ents[i].hostname, ents[i].port, 
++                               ents[i].protocol) || rc == DECLINED) {
++#endif /* EAPI */
+               if (r->method_number == M_CONNECT)
+                   rc = ap_proxy_connect_handler(r, cr, url, ents[i].hostname,
+                                              ents[i].port);
+@@ -377,6 +427,9 @@
+                                           ents[i].port);
+               else
+                   rc = DECLINED;
++#ifdef EAPI
++              }
++#endif /* EAPI */
+               /* an error or success */
+               if (rc != DECLINED && rc != HTTP_BAD_GATEWAY)
+@@ -390,6 +443,14 @@
+  * give up??
+  */
+     /* handle the scheme */
++#ifdef EAPI
++    if (ap_hook_use("ap::mod_proxy::handler",
++                  AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr),
++                  AP_HOOK_DECLINE(DECLINED),
++                  &rc, r, cr, url, 
++                    NULL, 0, scheme) && rc != DECLINED)
++        return rc;
++#endif /* EAPI */
+     if (r->method_number == M_CONNECT)
+       return ap_proxy_connect_handler(r, cr, url, NULL, 0);
+     if (strcasecmp(scheme, "http") == 0)
+@@ -895,4 +956,10 @@
+     NULL,                     /* child_init */
+     NULL,                     /* child_exit */
+     proxy_detect              /* post read-request */
++#ifdef EAPI
++   ,proxy_addmod,             /* EAPI: add_module */
++    proxy_remmod,             /* EAPI: remove_module */
++    NULL,                     /* EAPI: rewrite_command */
++    NULL                      /* EAPI: new_connection  */
++#endif
+ };
+diff -Nru apache_1.3.9/src/modules/proxy/proxy_http.c apache_1.3.9.EAPI/src/modules/proxy/proxy_http.c
+--- apache_1.3.9/src/modules/proxy/proxy_http.c        Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/modules/proxy/proxy_http.c   Wed Dec 29 22:02:34 1999
+@@ -181,8 +181,11 @@
+     pool *p = r->pool;
+     const long int zero = 0L;
+     char *destportstr = NULL;
+-    const char *urlptr = NULL;
++#ifdef EAPI
++    int destport = 0;
++#endif /* EAPI */
+     const char *datestr;
++    const char *urlptr = NULL;
+     struct tbl_do_args tdo;
+     struct addrinfo hints, *res, *tres;
+     int error;
+@@ -202,6 +205,17 @@
+     urlptr += 3;
+     ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT);
+     destportstr = portstr;
++
++#ifdef EAPI
++
++    ap_hook_use("ap::mod_proxy::http::handler::set_destport", 
++                AP_HOOK_SIG2(int,ptr), 
++                AP_HOOK_TOPMOST,
++                &destport, r);
++    ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT);
++    destportstr = portstr;
++#endif /* EAPI */
++
+     strp = strchr(urlptr, '/');
+     if (strp == NULL) {
+       desthost = ap_pstrdup(p, urlptr);
+@@ -374,13 +388,41 @@
+     f = ap_bcreate(p, B_RDWR | B_SOCKET);
+     ap_bpushfd(f, sock, sock);
++#ifdef EAPI
++    {
++        char *errmsg = NULL;
++        ap_hook_use("ap::mod_proxy::http::handler::new_connection", 
++                    AP_HOOK_SIG3(ptr,ptr,ptr), 
++                    AP_HOOK_DECLINE(NULL),
++                    &errmsg, r, f);
++        if (errmsg != NULL)
++            return ap_proxyerror(r, HTTP_BAD_GATEWAY, errmsg);
++    }
++#endif /* EAPI */
++
+     ap_hard_timeout("proxy send", r);
+     ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF,
+          NULL);
++#ifdef EAPI
++    {
++      int rc = DECLINED;
++      ap_hook_use("ap::mod_proxy::http::handler::write_host_header", 
++                  AP_HOOK_SIG6(int,ptr,ptr,ptr,int,ptr), 
++                  AP_HOOK_DECLINE(DECLINED),
++                  &rc, r, f, desthost, destport, destportstr);
++        if (rc == DECLINED) {
++          if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
++              ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
++          else
++              ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
++        }
++    }
++#else /* EAPI */
+     if (destportstr != NULL && atoi(destportstr) != DEFAULT_HTTP_PORT)
+       ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
+     else
+       ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
++#endif /* EAPI */
+     if (conf->viaopt == via_block) {
+       /* Block all outgoing Via: headers */
+diff -Nru apache_1.3.9/src/modules/standard/mod_define.c apache_1.3.9.EAPI/src/modules/standard/mod_define.c
+--- apache_1.3.9/src/modules/standard/mod_define.c     Thu Jan  1 01:00:00 1970
++++ apache_1.3.9.EAPI/src/modules/standard/mod_define.c        Wed Dec 29 21:25:56 1999
+@@ -0,0 +1,446 @@
++/* ====================================================================
++ * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer. 
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ *    software must display the following acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * 4. The names "Apache Server" and "Apache Group" must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission. For written permission, please contact
++ *    apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache"
++ *    nor may "Apache" appear in their names without prior written
++ *    permission of the Apache Group.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ *    acknowledgment:
++ *    "This product includes software developed by the Apache Group
++ *    for use in the Apache HTTP server project (http://www.apache.org/)."
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Group and was originally based
++ * on public domain software written at the National Center for
++ * Supercomputing Applications, University of Illinois, Urbana-Champaign.
++ * For more information on the Apache Group and the Apache HTTP server
++ * project, please see <http://www.apache.org/>.
++ *
++ */
++
++/*
++**  mod_define.c -- Apache module for configuration defines ($xxx)
++**  v1.0: Originally written in December 1998 by 
++**        Ralf S. Engelschall <rse@engelschall.com> and
++**        Christian Reiber <chrei@en.muc.de>
++**  v1.1: Completely Overhauled in August 1999 by
++**        Ralf S. Engelschall <rse@engelschall.com>
++*/
++
++#include "ap_config.h"
++#include "ap_ctype.h"
++#include "httpd.h"
++#include "http_config.h"
++#include "http_conf_globals.h"
++#include "http_core.h"
++#include "http_log.h"
++
++#ifndef EAPI
++#error "This module requires the Extended API (EAPI) facilities."
++#endif
++
++/* 
++ * The global table of defines
++ */
++
++static table *tDefines         = NULL;   /* global table of defines */
++static int    bOnceSeenADefine = FALSE;  /* optimization flag */
++
++/* 
++ * Forward declaration
++ */
++static int   DefineIndex      (pool *, char *, int *, int *, char **);
++static char *DefineFetch      (pool *, char *);
++static char *DefineExpand     (pool *, char *, int, char *);
++static void  DefineInit       (pool *);
++static void  DefineCleanup    (void *);
++static char *DefineRewriteHook(cmd_parms *, void *, const char *);
++
++/*
++ * Character classes for scanner function
++ */
++typedef enum {
++    CC_ESCAPE, CC_DOLLAR, CC_BRACEOPEN, CC_BRACECLOSE, 
++    CC_IDCHAR1, CC_IDCHAR, CC_OTHER, CC_EOS   
++} CharClass;
++
++/*
++ * Scanner states for scanner function
++ */
++typedef enum {
++    SS_NONE, SS_SKIP, SS_DOLLAR, SS_TOKEN_BRACED,
++    SS_TOKEN_UNBRACED, SS_ERROR, SS_FOUND
++} ScanState;
++
++/*
++ * Default meta characters
++ */
++#define DEFAULT_MC_ESCAPE      "\\"
++#define DEFAULT_MC_DOLLAR      "$"
++#define DEFAULT_MC_BRACEOPEN   "{"
++#define DEFAULT_MC_BRACECLOSE  "}"
++
++/*
++ * Scanner for variable constructs $xxx and ${xxx}
++ */
++static int DefineIndex(pool *p, char *cpLine, int *pos, int *len, char **cpVar)
++{
++    int rc;
++    char *cp;
++    char *cp2;
++    CharClass cc;
++    char cEscape;
++    char cDefine;
++    char cBraceOpen;
++    char cBraceClose;
++    char *cpError;
++    ScanState s;
++
++    cEscape = DEFAULT_MC_ESCAPE[0];
++    if ((cp = DefineFetch(p, "mod_define::escape")) != NULL)
++        cEscape = cp[0];
++    cDefine = DEFAULT_MC_DOLLAR[0];
++    if ((cp = DefineFetch(p, "mod_define::dollar")) != NULL)
++        cDefine = cp[0];
++    cBraceOpen = DEFAULT_MC_BRACEOPEN[0];
++    if ((cp = DefineFetch(p, "mod_define::braceopen")) != NULL)
++        cBraceOpen = cp[0];
++    cBraceClose = DEFAULT_MC_BRACECLOSE[0];
++    if ((cp = DefineFetch(p, "mod_define::braceclose")) != NULL)
++        cBraceClose = cp[0];
++
++    rc = 0;
++    *len = 0;
++    cc = CC_OTHER;
++    s = SS_NONE;
++    for (cp = cpLine+(*pos); cc != CC_EOS; cp++) {
++        if (*cp == cEscape)
++            cc = CC_ESCAPE;
++        else if (*cp == cDefine)
++            cc = CC_DOLLAR;
++        else if (*cp == cBraceOpen)
++            cc = CC_BRACEOPEN;
++        else if (*cp == cBraceClose)
++            cc = CC_BRACECLOSE;
++        else if (ap_isalpha(*cp))
++            cc = CC_IDCHAR1;
++        else if (ap_isdigit(*cp) || *cp == '_' || *cp == ':')
++            cc = CC_IDCHAR;
++        else if (*cp == '\0')
++            cc = CC_EOS;
++        else
++            cc = CC_OTHER;
++        switch (s) {
++            case SS_NONE:
++                switch (cc) {
++                    case CC_ESCAPE: 
++                        s = SS_SKIP;
++                        break;
++                    case CC_DOLLAR: 
++                        s = SS_DOLLAR; 
++                        break;
++                    default:
++                        break;
++                }
++                break;
++            case SS_SKIP:
++                s = SS_NONE;
++                continue;
++                break;
++            case SS_DOLLAR:
++                switch (cc) {
++                    case CC_BRACEOPEN: 
++                        s = SS_TOKEN_BRACED;   
++                        *pos = cp-cpLine-1; 
++                        (*len) = 2; 
++                        *cpVar = cp+1; 
++                        break;
++                    case CC_IDCHAR1: 
++                        s = SS_TOKEN_UNBRACED; 
++                        *pos = cp-cpLine-1; 
++                        (*len) = 2; 
++                        *cpVar = cp; 
++                        break;
++                    case CC_ESCAPE:
++                        s = SS_SKIP; 
++                        break;
++                    default: 
++                        s = SS_NONE; 
++                        break;
++                }
++                break;
++            case SS_TOKEN_BRACED:
++                switch (cc) {
++                    case CC_IDCHAR1:
++                    case CC_IDCHAR: 
++                        (*len)++; 
++                        break;
++                    case CC_BRACECLOSE: 
++                        (*len)++; 
++                        cp2 = ap_palloc(p, cp-*cpVar+1);
++                        ap_cpystrn(cp2, *cpVar, cp-*cpVar+1); 
++                        *cpVar = cp2;
++                        s = SS_FOUND; 
++                        break;
++                    default:
++                        cpError = ap_psprintf(p, "Illegal character '%c' in identifier", *cp);
++                        s = SS_ERROR;
++                        break;
++                }
++                break;
++            case SS_TOKEN_UNBRACED:
++                switch (cc) {
++                    case CC_IDCHAR1:
++                    case CC_IDCHAR: 
++                        (*len)++; 
++                        break;
++                    default:
++                        cp2 = ap_palloc(p, cp-*cpVar+1);
++                        ap_cpystrn(cp2, *cpVar, cp-*cpVar+1); 
++                        *cpVar = cp2;
++                        s = SS_FOUND; 
++                        break;
++                }
++                break;
++            case SS_FOUND:
++            case SS_ERROR:
++                break;
++        }
++        if (s == SS_ERROR) {
++            fprintf(stderr, "Error\n");
++            break;
++        }
++        else if (s == SS_FOUND) {
++            rc = 1;
++            break;
++        }
++    }
++    return rc;
++}
++
++/*
++ * Determine the value of a variable
++ */
++static char *DefineFetch(pool *p, char *cpVar)
++{
++    char *cpVal;
++
++    /* first try out table */
++    if ((cpVal = (char *)ap_table_get(tDefines, (char *)cpVar)) != NULL)
++        return cpVal;
++    /* second try the environment */
++    if ((cpVal = getenv(cpVar)) != NULL)
++        return cpVal;
++    return NULL;
++}
++
++/*
++ * Expand a variable
++ */
++static char *DefineExpand(pool *p, char *cpToken, int tok_len, char *cpVal)
++{
++    char *cp;
++    int val_len, rest_len;
++
++    val_len  = strlen(cpVal);
++    rest_len = strlen(cpToken+tok_len);
++    if (val_len < tok_len) 
++        memcpy(cpToken+val_len, cpToken+tok_len, rest_len+1);
++    else if (val_len > tok_len)
++        for (cp = cpToken+strlen(cpToken); cp > cpToken+tok_len-1; cp--)  
++            *(cp+(val_len-tok_len)) = *cp;
++    memcpy(cpToken, cpVal, val_len);
++    return NULL;
++}
++
++/*
++ * The EAPI hook which is called after Apache has read a
++ * configuration line and before it's actually processed
++ */
++static char *DefineRewriteHook(cmd_parms *cmd, void *config, const char *line)
++{
++    pool *p;
++    char *cpBuf;
++    char *cpLine;
++    int pos;
++    int len;
++    char *cpError;
++    char *cpVar;
++    char *cpVal;
++    server_rec *s;
++
++    /* runtime optimization */
++    if (!bOnceSeenADefine)
++        return NULL;
++
++    p  = cmd->pool;
++    s  = cmd->server;
++
++    /*
++     * Search for:
++     *  ....\$[a-zA-Z][:_a-zA-Z0-9]*....
++     *  ....\${[a-zA-Z][:_a-zA-Z0-9]*}....
++     */
++    cpBuf = NULL;
++    cpLine = (char *)line;
++    pos = 0;
++    while (DefineIndex(p, cpLine, &pos, &len, &cpVar)) {
++#ifdef DEFINE_DEBUG
++        {
++        char prefix[1024];
++        char marker[1024];
++        int i;
++        for (i = 0; i < pos; i++)
++            prefix[i] = ' ';
++        prefix[i] = '\0';
++        for (i = 0; i < len; i++)
++            marker[i] = '^';
++        marker[i] = '\0';
++        fprintf(stderr, 
++                "Found variable `%s' (pos: %d, len: %d)\n"
++                "  %s\n"
++                "  %s%s\n",
++                cpVar, pos, len, cpLine, prefix, marker);
++        }
++#endif
++        if (cpBuf == NULL) {
++            cpBuf = ap_palloc(p, MAX_STRING_LEN);
++            ap_cpystrn(cpBuf, line, MAX_STRING_LEN);
++            cpLine = cpBuf;
++        }
++        if ((cpVal = DefineFetch(p, cpVar)) == NULL) {
++            ap_log_error(APLOG_MARK, APLOG_ERR, s, 
++                         "mod_define: Variable '%s' not defined: file %s, line %d", 
++                         cpVar, cmd->config_file->name,
++                         cmd->config_file->line_number);
++            cpBuf = NULL;
++            break;
++        }
++        if ((cpError = DefineExpand(p, cpLine+pos, len, cpVal)) != NULL) {
++            ap_log_error(APLOG_MARK, APLOG_ERR, s, 
++                         "mod_define: %s: file %s, line %d", 
++                         cpError, cmd->config_file->name,
++                         cmd->config_file->line_number);
++            cpBuf = NULL;
++            break;
++        }
++    }
++    return cpBuf;
++}
++
++/*
++ * Implementation of the `Define' configuration directive
++ */
++static const char *cmd_define(cmd_parms *cmd, void *config, 
++                              char *cpVar, char *cpVal)
++{
++    if (tDefines == NULL)
++        DefineInit(cmd->pool);
++    ap_table_set(tDefines, cpVar, cpVal);
++    bOnceSeenADefine = TRUE;
++    return NULL;
++}
++
++/*
++ * Module Initialization
++ */
++
++static void DefineInit(pool *p)
++{
++    tDefines = ap_make_table(p, 10);
++    /* predefine delimiters */
++    ap_table_set(tDefines, "mod_define::escape", DEFAULT_MC_ESCAPE);
++    ap_table_set(tDefines, "mod_define::dollar", DEFAULT_MC_DOLLAR);
++    ap_table_set(tDefines, "mod_define::open",   DEFAULT_MC_BRACEOPEN);
++    ap_table_set(tDefines, "mod_define::close",  DEFAULT_MC_BRACECLOSE);
++    ap_register_cleanup(p, NULL, DefineCleanup, ap_null_cleanup);
++    return;
++}
++
++/*
++ * Module Cleanup
++ */
++
++static void DefineCleanup(void *data)
++{
++    /* reset private variables when config pool is cleared */
++    tDefines         = NULL;
++    bOnceSeenADefine = FALSE;
++    return;
++}
++
++/* 
++ * Module Directive lists
++ */
++static const command_rec DefineDirectives[] = {
++    { "Define", cmd_define, NULL, RSRC_CONF|ACCESS_CONF, TAKE2,
++      "Define a configuration variable" },
++    { NULL }
++};
++
++/* 
++ * Module API dispatch list
++ */
++module MODULE_VAR_EXPORT define_module = {
++    STANDARD_MODULE_STUFF, 
++    NULL,                  /* module initializer                  */
++    NULL,                  /* create per-dir    config structures */
++    NULL,                  /* merge  per-dir    config structures */
++    NULL,                  /* create per-server config structures */
++    NULL,                  /* merge  per-server config structures */
++    DefineDirectives,      /* table of config file commands       */
++    NULL,                  /* [#8] MIME-typed-dispatched handlers */
++    NULL,                  /* [#1] URI to filename translation    */
++    NULL,                  /* [#4] validate user id from request  */
++    NULL,                  /* [#5] check if the user is ok _here_ */
++    NULL,                  /* [#2] check access by host address   */
++    NULL,                  /* [#6] determine MIME type            */
++    NULL,                  /* [#7] pre-run fixups                 */
++    NULL,                  /* [#9] log a transaction              */
++    NULL,                  /* [#3] header parser                  */
++    NULL,                  /* child_init                          */
++    NULL,                  /* child_exit                          */
++    NULL,                  /* [#0] post read-request              */
++    NULL,                  /* EAPI: add_module                    */
++    NULL,                  /* EAPI: del_module                    */
++    DefineRewriteHook,     /* EAPI: rewrite_command               */
++    NULL                   /* EAPI: new_connection                */
++};
++
+diff -Nru apache_1.3.9/src/modules/standard/mod_log_config.c apache_1.3.9.EAPI/src/modules/standard/mod_log_config.c
+--- apache_1.3.9/src/modules/standard/mod_log_config.c Wed Dec 29 22:03:42 1999
++++ apache_1.3.9.EAPI/src/modules/standard/mod_log_config.c    Wed Dec 29 21:25:56 1999
+@@ -252,6 +252,9 @@
+ typedef const char *(*item_key_func) (request_rec *, char *);
+ typedef struct {
++#ifdef EAPI
++    char ch;
++#endif
+     item_key_func func;
+     char *arg;
+     int condition_sense;
+@@ -511,15 +514,36 @@
+     }
+ };
++#ifdef EAPI
++static struct log_item_list *find_log_func(pool *p, char k)
++#else /* EAPI */
+ static struct log_item_list *find_log_func(char k)
++#endif /* EAPI */
+ {
+     int i;
++#ifdef EAPI
++    struct log_item_list *lil;
++#endif /* EAPI */
+     for (i = 0; log_item_keys[i].ch; ++i)
+         if (k == log_item_keys[i].ch) {
+             return &log_item_keys[i];
+         }
++#ifdef EAPI
++    if (ap_hook_status(ap_psprintf(p, "ap::mod_log_config::log_%c", k)) 
++        != AP_HOOK_STATE_NOTEXISTANT) {
++        lil = (struct log_item_list *)
++              ap_pcalloc(p, sizeof(struct log_item_list));
++        if (lil == NULL)
++            return NULL;
++        lil->ch = k;
++        lil->func = NULL;
++        lil->want_orig_default = 0;
++        return lil;
++    }
++#endif /* EAPI */
++
+     return NULL;
+ }
+@@ -645,7 +669,11 @@
+             break;
+         default:
++#ifdef EAPI
++            l = find_log_func(p, *s++);
++#else /* EAPI */
+             l = find_log_func(*s++);
++#endif /* EAPI */
+             if (!l) {
+                 char dummy[2];
+@@ -654,6 +682,9 @@
+                 return ap_pstrcat(p, "Unrecognized LogFormat directive %",
+                                dummy, NULL);
+             }
++#ifdef EAPI
++            it->ch = s[-1];
++#endif
+             it->func = l->func;
+             if (it->want_orig == -1) {
+                 it->want_orig = l->want_orig_default;
+@@ -715,6 +746,15 @@
+     /* We do.  Do it... */
++#ifdef EAPI
++    if (item->func == NULL) {
++        cp = NULL;
++        ap_hook_use(ap_psprintf(r->pool, "ap::mod_log_config::log_%c", item->ch),
++                    AP_HOOK_SIG3(ptr,ptr,ptr), AP_HOOK_DECLINE(NULL),
++                    &cp, r, item->arg);
++    }
++    else
++#endif
+     cp = (*item->func) (item->want_orig ? orig : r, item->arg);
+     return cp ? cp : "-";
+ }
+diff -Nru apache_1.3.9/src/modules/standard/mod_rewrite.c apache_1.3.9.EAPI/src/modules/standard/mod_rewrite.c
+--- apache_1.3.9/src/modules/standard/mod_rewrite.c    Wed Dec 29 22:03:43 1999
++++ apache_1.3.9.EAPI/src/modules/standard/mod_rewrite.c       Wed Dec 29 21:25:56 1999
+@@ -3746,6 +3746,15 @@
+     }
+ #endif /* ndef WIN32 */
++#ifdef EAPI
++    else {
++        ap_hook_use("ap::mod_rewrite::lookup_variable",
++                    AP_HOOK_SIG3(ptr,ptr,ptr), 
++                    AP_HOOK_DECLINE(NULL),
++                    &result, r, var);
++    }
++#endif
++
+     if (result == NULL) {
+         return ap_pstrdup(r->pool, "");
+     }
+diff -Nru apache_1.3.9/src/modules/standard/mod_so.c apache_1.3.9.EAPI/src/modules/standard/mod_so.c
+--- apache_1.3.9/src/modules/standard/mod_so.c Wed Dec 29 22:03:43 1999
++++ apache_1.3.9.EAPI/src/modules/standard/mod_so.c    Wed Dec 29 21:25:56 1999
+@@ -257,7 +257,12 @@
+      * Make sure the found module structure is really a module structure
+      * 
+      */
++#ifdef EAPI
++    if (   modp->magic != MODULE_MAGIC_COOKIE_AP13 
++        && modp->magic != MODULE_MAGIC_COOKIE_EAPI) {
++#else
+     if (modp->magic != MODULE_MAGIC_COOKIE) {
++#endif
+         return ap_pstrcat(cmd->pool, "API module structure `", modname,
+                           "' in file ", szModuleFile, " is garbled -"
+                           " perhaps this is not an Apache module DSO?", NULL);
+diff -Nru apache_1.3.9/src/modules/standard/mod_status.c apache_1.3.9.EAPI/src/modules/standard/mod_status.c
+--- apache_1.3.9/src/modules/standard/mod_status.c     Wed Dec 29 22:03:43 1999
++++ apache_1.3.9.EAPI/src/modules/standard/mod_status.c        Wed Dec 29 21:25:56 1999
+@@ -480,12 +480,33 @@
+           if (no_table_report)
+               ap_rputs("<p><hr><h2>Server Details</h2>\n\n", r);
+           else
++#ifndef NO_PRETTYPRINT
++              ap_rputs("<p>\n\n<table bgcolor=\"#ffffff\" border=\"0\">"
++                      "<tr bgcolor=000000>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Srv</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>PID</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Acc</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>M</b></font></td>"
++#ifndef NO_TIMES
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>CPU</b></font></td>"
++#endif
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>SS</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Req</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Conn</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Child</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Slot</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Host</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>VHost</b></font></td>"
++                      "<td><font face=\"Arial,Helvetica\" color=\"#ffffff\"><b>Request</b></td>"
++                      "</tr>\n", r);      
++#else /* NO_PRETTYPRINT */
+ #ifdef NO_TIMES
+               /* Allow for OS/2 not having CPU stats */
+               ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
+ #else
+               ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M<th>CPU\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
+ #endif
++#endif /* NO_PRETTYPRINT */
+       }
+       for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
+@@ -602,14 +623,19 @@
+                           vhost ? vhost->server_hostname : "(unavailable)");
+                   }
+                   else {              /* !no_table_report */
++#ifndef NO_PRETTYPRINT
++                      ap_rprintf(r,"<tr bgcolor=\"#ffffff\">");
++#else
++                      ap_rprintf(r,"<tr>");
++#endif
+                       if (score_record.status == SERVER_DEAD)
+                           ap_rprintf(r,
+-                              "<tr><td><b>%d-%d</b><td>-<td>%d/%lu/%lu",
++                              "<td><b>%d-%d</b><td>-<td>%d/%lu/%lu",
+                               i, (int) ps_record.generation,
+                               (int) conn_lres, my_lres, lres);
+                       else
+                           ap_rprintf(r,
+-                              "<tr><td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
++                              "<td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
+                               i, (int) ps_record.generation,
+                               (int) ps_record.pid, (int) conn_lres,
+                               my_lres, lres);
+@@ -669,11 +695,22 @@
+                           ap_rprintf(r,
+                            "<td>?<td nowrap>?<td nowrap>..reading.. </tr>\n\n");
+                       else
++#ifndef NO_PRETTYPRINT
++                          ap_rprintf(r,
++                           "<td nowrap><font face=\"Arial,Helvetica\" size=\"-1\">%s</font>"
++                           "<td nowrap><font face=\"Arial,Helvetica\" size=\"-1\">%s</font>"
++                           "<td nowrap><font face=\"Arial,Helvetica\" size=\"-1\">%s</font>"
++                           "</tr>\n\n",
++                           score_record.client,
++                           vhost ? vhost->server_hostname : "(unavailable)",
++                           ap_escape_html(r->pool, score_record.request));
++#else
+                           ap_rprintf(r,
+                            "<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n",
+                            score_record.client,
+                            vhost ? vhost->server_hostname : "(unavailable)",
+                            ap_escape_html(r->pool, score_record.request));
++#endif
+                   }           /* no_table_report */
+               }                       /* !short_report */
+           }                   /* if (<active child>) */
+@@ -711,6 +748,12 @@
+ </table>\n", r);
+ #endif
+       }
++
++#ifdef EAPI
++    ap_hook_use("ap::mod_status::display",
++                AP_HOOK_SIG4(void,ptr,int,int), AP_HOOK_ALL,
++                r, no_table_report, short_report);
++#endif
+     } else {
+diff -Nru apache_1.3.9/src/support/apxs.pl apache_1.3.9.EAPI/src/support/apxs.pl
+--- apache_1.3.9/src/support/apxs.pl   Wed Dec 29 22:03:43 1999
++++ apache_1.3.9.EAPI/src/support/apxs.pl      Wed Dec 29 21:25:56 1999
+@@ -651,5 +651,11 @@
+     NULL,                  /* child_init                          */
+     NULL,                  /* child_exit                          */
+     NULL                   /* [#0] post read-request              */
++#ifdef EAPI
++   ,NULL,                  /* EAPI: add_module                    */
++    NULL,                  /* EAPI: remove_module                 */
++    NULL,                  /* EAPI: rewrite_command               */
++    NULL                   /* EAPI: new_connection                */
++#endif
+ };
+diff -Nru apache_1.3.9/src/support/httpd.exp apache_1.3.9.EAPI/src/support/httpd.exp
+--- apache_1.3.9/src/support/httpd.exp Wed Dec 29 22:03:43 1999
++++ apache_1.3.9.EAPI/src/support/httpd.exp    Wed Dec 29 21:25:56 1999
+@@ -410,3 +410,59 @@
+ XML_SetUnparsedEntityDeclHandler
+ XML_SetUserData
+ XML_UseParserAsHandlerArg
++ap_add_config_define
++ap_make_shared_sub_pool
++ap_global_ctx
++ap_ctx_new
++ap_ctx_get
++ap_ctx_set
++ap_hook_init
++ap_hook_kill
++ap_hook_configure
++ap_hook_register_I
++ap_hook_unregister_I
++ap_hook_status
++ap_hook_use
++ap_hook_call
++ap_mm_useable
++ap_MM_create
++ap_MM_permission
++ap_MM_destroy
++ap_MM_lock
++ap_MM_unlock
++ap_MM_malloc
++ap_MM_realloc
++ap_MM_free
++ap_MM_calloc
++ap_MM_strdup
++ap_MM_sizeof
++ap_MM_maxsize
++ap_MM_available
++ap_MM_error
++ap_mm_create
++ap_mm_permission
++ap_mm_destroy
++ap_mm_lock
++ap_mm_unlock
++ap_mm_malloc
++ap_mm_realloc
++ap_mm_free
++ap_mm_calloc
++ap_mm_strdup
++ap_mm_sizeof
++ap_mm_maxsize
++ap_mm_available
++ap_mm_error
++ap_mm_display_info
++ap_mm_core_create
++ap_mm_core_permission
++ap_mm_core_delete
++ap_mm_core_size
++ap_mm_core_lock
++ap_mm_core_unlock
++ap_mm_core_maxsegsize
++ap_mm_core_align2page
++ap_mm_core_align2word
++ap_mm_lib_error_set
++ap_mm_lib_error_get
++ap_mm_lib_version
This page took 0.207944 seconds and 4 git commands to generate.