diff -Nru apache_1.3.12/htdocs/manual/mod/directives.html apache_1.3.12.new/htdocs/manual/mod/directives.html --- apache_1.3.12/htdocs/manual/mod/directives.html Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/htdocs/manual/mod/directives.html Mon Mar 13 19:29:56 2000 @@ -99,6 +99,7 @@
  • DefaultIcon
  • DefaultLanguage
  • DefaultType +
  • Define
  • deny
  • <Directory>
  • <DirectoryMatch> diff -Nru apache_1.3.12/htdocs/manual/mod/index.html apache_1.3.12.new/htdocs/manual/mod/index.html --- apache_1.3.12/htdocs/manual/mod/index.html Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/htdocs/manual/mod/index.html Mon Mar 13 19:29:55 2000 @@ -62,6 +62,8 @@
    mod_cookies up to Apache 1.1.1
    Support for Netscape-like cookies. Replaced in Apache 1.2 by mod_usertrack +
    mod_define +
    Variable Definition for Arbitrary Directives
    mod_digest
    MD5 authentication
    mod_dir diff -Nru apache_1.3.12/htdocs/manual/mod/mod_define.html apache_1.3.12.new/htdocs/manual/mod/mod_define.html --- apache_1.3.12/htdocs/manual/mod/mod_define.html Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/htdocs/manual/mod/mod_define.html Fri Aug 27 11:23:39 1999 @@ -0,0 +1,135 @@ + + + + + + +Apache module mod_define + + + + +
    + + +
    +

    Module mod_define

    +

    Variable Definition For Arbitrary Directives

    + +This module is contained in the mod_define.c 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 mod_define you have +to enable the following line in the server build Configuration +file: + +

    +

    +    AddModule  modules/extra/mod_define.o
    +
    + +

    +


    + +

    Define

    +Syntax: + Define variable value
    +Default: + none
    +Context: + server config, virtual host, directory, .htaccess
    +Override: none
    +Status: Extension
    +Module: mod_define.c
    +Compatibility: Apache+EAPI
    + +

    +The Define directive defines a variable which later can be +expanded with the unsafe but short construct +``$variable'' or the safe but longer construct +``${variable}'' on any configuration line. +Do not intermix this with the third-party module mod_macro. The +mod_define 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 ``$variable'' expands has +to fit into one line. When you need macros which can span more lines, you've +to use mod_macro. OTOH mod_macro cannot be used to +expand a variable/macro on an arbitrary directive line. So, the typical use +case of mod_define is to make strings variable (and this +way easily changeable at one location) and not to bundle things +together (as it's the typical use case for macros). + +

    +The syntax of the expansion construct ( +``${variable}'') follows the Perl and Shell +syntax, but can be changed via the Define directive, too. Four +internal variables can be used for this. The default is: + +

    +
    +Define mod_define::escape "\\"
    +Define mod_define::dollar "$"
    +Define mod_define::open   "{"
    +Define mod_define::close  "}"
    +
    +
    + +

    +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. + +

    +Example: +

    +
    +Define master     "Joe Average <joe@average.dom>"
    +Define docroot    /usr/local/apache/htdocs
    +Define hostname   foo
    +Define domainname bar.dom
    +Define portnumber 80
    +  :
    +<VirtualHost $hostname.$domainname:$portnumber>
    +SetEnv       SERVER_MASTER "$master"
    +ServerName   $hostname.$domainname
    +ServerAlias  $hostname
    +Port         $portnumber
    +DocumentRoot $docroot
    +<Directory $docroot>
    +  :
    +<Directory>
    +
    +
    + + +
    + + + diff -Nru apache_1.3.12/src/ApacheCore.def apache_1.3.12.new/src/ApacheCore.def --- apache_1.3.12/src/ApacheCore.def Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/ApacheCore.def Mon Mar 13 19:30:30 2000 @@ -360,3 +360,17 @@ ap_SHA1Final @355 ap_sha1_base64 @356 ap_send_error_response @357 + ap_add_config_define @358 + ap_global_ctx @359 + ap_ctx_new @360 + ap_ctx_get @361 + ap_ctx_set @362 + ap_hook_init @363 + ap_hook_kill @364 + ap_hook_configure @365 + ap_hook_register_I @366 + ap_hook_unregister_I @367 + ap_hook_status @368 + ap_hook_use @369 + ap_hook_call @370 + diff -Nru apache_1.3.12/src/Configuration.tmpl apache_1.3.12.new/src/Configuration.tmpl --- apache_1.3.12/src/Configuration.tmpl Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/Configuration.tmpl Mon Mar 13 19:39:11 2000 @@ -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 @@ -242,6 +260,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.12/src/Configure apache_1.3.12.new/src/Configure --- apache_1.3.12/src/Configure Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/Configure Mon Mar 13 19:30:30 2000 @@ -1727,6 +1727,72 @@ 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. ## if [ -d ./lib/expat-lite/ ]; then diff -Nru apache_1.3.12/src/ap/Makefile.tmpl apache_1.3.12.new/src/ap/Makefile.tmpl --- apache_1.3.12/src/ap/Makefile.tmpl Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/ap/Makefile.tmpl Mon Mar 13 19:30:30 2000 @@ -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.12/src/ap/ap.mak apache_1.3.12.new/src/ap/ap.mak --- apache_1.3.12/src/ap/ap.mak Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/ap/ap.mak Mon Mar 13 19:30:30 2000 @@ -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.12/src/ap/ap_ctx.c apache_1.3.12.new/src/ap/ap_ctx.c --- apache_1.3.12/src/ap/ap_ctx.c Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/ap/ap_ctx.c Thu Dec 30 22:02:56 1999 @@ -0,0 +1,155 @@ +/* ==================================================================== + * Copyright (c) 1998-2000 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 . + * + */ + +/* +** Generic Context Interface for Apache +** Written by Ralf S. Engelschall +*/ + +#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.12/src/ap/ap_hook.c apache_1.3.12.new/src/ap/ap_hook.c --- apache_1.3.12/src/ap/ap_hook.c Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/ap/ap_hook.c Thu Dec 30 22:02:56 1999 @@ -0,0 +1,930 @@ +#if 0 +=pod +#endif +/* ==================================================================== + * Copyright (c) 1998-2000 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 . + * + */ + +/* +** Implementation of a Generic Hook Interface for Apache +** Written by Ralf S. Engelschall +** +** 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 (); + 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 (); +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.12/src/ap/ap_mm.c apache_1.3.12.new/src/ap/ap_mm.c --- apache_1.3.12/src/ap/ap_mm.c Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/ap/ap_mm.c Thu Dec 30 22:02:56 1999 @@ -0,0 +1,178 @@ +/* ==================================================================== + * Copyright (c) 1999-2000 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 . + */ + +/* +** 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.12/src/include/alloc.h apache_1.3.12.new/src/include/alloc.h --- apache_1.3.12/src/include/alloc.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/alloc.h Mon Mar 13 19:30:30 2000 @@ -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.12/src/include/ap_ctx.h apache_1.3.12.new/src/include/ap_ctx.h --- apache_1.3.12/src/include/ap_ctx.h Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/include/ap_ctx.h Thu Dec 30 22:02:59 1999 @@ -0,0 +1,110 @@ +/* ==================================================================== + * Copyright (c) 1998-2000 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 . + * + */ + +/* +** Generic Context Interface for Apache +** Written by Ralf S. Engelschall +*/ + +#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.12/src/include/ap_hook.h apache_1.3.12.new/src/include/ap_hook.h --- apache_1.3.12/src/include/ap_hook.h Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/include/ap_hook.h Thu Dec 30 22:02:59 1999 @@ -0,0 +1,710 @@ +#if 0 +=cut +#endif +/* ==================================================================== + * Copyright (c) 1998-2000 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 . + * + */ + +/* +** Implementation of a Generic Hook Interface for Apache +** Written by Ralf S. Engelschall +** +** 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< - B + +=head1 SYNOPSIS + +B + + void ap_hook_init(void); + void ap_hook_kill(void); + +B + + 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 + + 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 (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 (ap_hook_mode): + + AP_HOOK_TOPMOST + AP_HOOK_DECLINE(value) + AP_HOOK_DECLTMP(value) + AP_HOOK_ALL + +B (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 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 for the I (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 with the signature C +(where the second argument is C 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 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. + +A hook named C with the signature C 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. + +A hook named C with the signature C 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. + +A hook named C with the signature C and a return +code semantic which says: All registered functions on the hook functioin stack +are tried. Sample idea: I. + +=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 under the C hook with the +private context given by the variable C. And it registers the +function C under the C hook without any context. Same for +C and C. + +=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) for the C +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 (except for +functions which have a void return type, of course). + +BTW, the return value of C is always C or C. +C when at least one function call was successful (always the case for +C and C). C 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 and the +corresponding code can be automatically generated by running ``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 +file. + +=head1 EXAMPLE + +We want to call `C' through hooks in order +to allow modules to override this call. So, somewhere we have a replacement +function for C defined (same signature, of course): + + ssize_t my_read(int, void *, size_t); + +We now configure a C hook. Here the C macro defines the +signature of the C-like callback functions and has to match the +prototype of C. But we have to replace typedefs with the physical +underlaying ANSI C types. And C 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 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 call and registers the +C 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. Now we can +replace the standard C 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' is done. When it returns not -1 (the decline value) nothing +more is done. But when C returns -1 the next function is tried: +`C'. 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. + +=head1 AUTHOR + + Ralf S. Engelschall + rse@engelschall.com + www.engelschall.com + +=cut +*/ diff -Nru apache_1.3.12/src/include/ap_mm.h apache_1.3.12.new/src/include/ap_mm.h --- apache_1.3.12/src/include/ap_mm.h Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/include/ap_mm.h Thu Dec 30 22:02:59 1999 @@ -0,0 +1,130 @@ +/* ==================================================================== + * Copyright (c) 1999-2000 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 . + */ + +/* +** +** 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.12/src/include/ap_mmn.h apache_1.3.12.new/src/include/ap_mmn.h --- apache_1.3.12/src/include/ap_mmn.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/ap_mmn.h Mon Mar 13 19:30:30 2000 @@ -229,7 +229,23 @@ * 19990320.7 - add ap_strcasestr() */ +/* + * 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.12/src/include/buff.h apache_1.3.12.new/src/include/buff.h --- apache_1.3.12/src/include/buff.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/buff.h Mon Mar 13 19:30:30 2000 @@ -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.12/src/include/http_conf_globals.h apache_1.3.12.new/src/include/http_conf_globals.h --- apache_1.3.12/src/include/http_conf_globals.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/http_conf_globals.h Mon Mar 13 19:30:30 2000 @@ -91,6 +91,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.12/src/include/http_config.h apache_1.3.12.new/src/include/http_config.h --- apache_1.3.12/src/include/http_config.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/http_config.h Mon Mar 13 19:30:30 2000 @@ -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 () + * 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.12/src/include/http_main.h apache_1.3.12.new/src/include/http_main.h --- apache_1.3.12/src/include/http_main.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/http_main.h Mon Mar 13 19:30:30 2000 @@ -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.12/src/include/httpd.h apache_1.3.12.new/src/include/httpd.h --- apache_1.3.12/src/include/httpd.h Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/include/httpd.h Mon Mar 13 19:30:30 2000 @@ -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" @@ -140,8 +152,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 --- */ @@ -353,6 +370,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. @@ -438,6 +468,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. @@ -819,6 +852,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 */ }; @@ -867,6 +904,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... */ @@ -939,6 +979,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.12/src/main/alloc.c apache_1.3.12.new/src/main/alloc.c --- apache_1.3.12/src/main/alloc.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/main/alloc.c Mon Mar 13 19:30:30 2000 @@ -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,74 @@ 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, + ap_psprintf(permanent_pool, "%s.%ld", + EAPI_MM_CORE_PATH, (long)getpid())); + 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); + 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 +712,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 +726,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 +744,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 +933,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 +1069,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 +1094,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 +1117,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 +1147,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 +1164,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.12/src/main/buff.c apache_1.3.12.new/src/main/buff.c --- apache_1.3.12/src/main/buff.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/main/buff.c Mon Mar 13 19:30:30 2000 @@ -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; @@ -193,8 +197,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; @@ -257,6 +264,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; @@ -268,6 +278,9 @@ #if defined (WIN32) || defined(NETWARE) 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(); @@ -315,6 +328,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 @@ -341,6 +357,9 @@ #if defined(WIN32) || defined(NETWARE) 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(); @@ -421,6 +440,10 @@ (size_t) SF_UNBOUND, 1, SF_WRITE); #endif +#ifdef EAPI + fb->ctx = ap_ctx_new(p); +#endif /* EAPI */ + return fb; } @@ -1067,6 +1090,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.12/src/main/http_config.c apache_1.3.12.new/src/main/http_config.c --- apache_1.3.12/src/main/http_config.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/main/http_config.c Mon Mar 13 19:30:30 2000 @@ -582,6 +582,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 */ } /* @@ -596,6 +610,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); @@ -1444,6 +1498,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.12/src/main/http_main.c apache_1.3.12.new/src/main/http_main.c --- apache_1.3.12/src/main/http_main.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/main/http_main.c Mon Mar 13 19:30:30 2000 @@ -259,6 +259,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 @@ -441,6 +444,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 */ + #ifndef NETWARE static APACHE_TLS int volatile exit_after_unblock = 0; #endif @@ -1191,6 +1218,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); @@ -1199,6 +1230,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; @@ -1264,7 +1298,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; @@ -1500,10 +1538,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 */ @@ -2203,6 +2247,9 @@ #endif /* Clear the pool - including any registered cleanups */ ap_destroy_pool(pglobal); +#ifdef EAPI + ap_kill_alloc_shared(); +#endif exit(code); } @@ -3211,6 +3258,24 @@ conn->remote_addr = *remaddr; conn->remote_ip = ap_pstrdup(conn->pool, inet_ntoa(conn->remote_addr.sin_addr)); +#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; } @@ -3617,6 +3682,15 @@ 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"); +#ifdef EAPI_MM_CORE_PATH + printf(" -D EAPI_MM_CORE_PATH=\"" EAPI_MM_CORE_PATH "\"\n"); +#endif +#endif #ifdef BIG_SECURITY_HOLE printf(" -D BIG_SECURITY_HOLE\n"); #endif @@ -3770,6 +3844,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 @@ -4191,6 +4281,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); } @@ -4219,6 +4312,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 @@ -4229,6 +4325,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); } @@ -4953,16 +5052,31 @@ 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"); +#ifdef EAPI + clean_parent_exit(0); +#else exit(0); +#endif } if (ap_dump_settings) { +#ifdef EAPI + clean_parent_exit(0); +#else exit(0); +#endif } child_timeouts = !ap_standalone || one_process; @@ -5098,6 +5212,10 @@ ap_destroy_pool(r->pool); } +#ifdef EAPI + ap_call_close_connection_hook(conn); +#endif /* EAPI */ + ap_bclose(cio); } exit(0); @@ -5449,6 +5567,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 @@ -5459,6 +5580,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); } @@ -6785,6 +6909,9 @@ } } +#ifdef EAPI + ap_init_alloc_shared(TRUE); +#endif if (!ap_os_is_path_absolute(ap_server_confname)) { char *full_conf_path; @@ -6818,6 +6945,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.12/src/main/http_protocol.c apache_1.3.12.new/src/main/http_protocol.c --- apache_1.3.12/src/main/http_protocol.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/main/http_protocol.c Mon Mar 13 19:30:30 2000 @@ -1028,6 +1028,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 @@ -1174,6 +1178,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.12/src/main/http_request.c apache_1.3.12.new/src/main/http_request.c --- apache_1.3.12/src/main/http_request.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/main/http_request.c Mon Mar 13 19:30:30 2000 @@ -1316,6 +1316,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.12/src/modules/extra/mod_define.c apache_1.3.12.new/src/modules/extra/mod_define.c --- apache_1.3.12/src/modules/extra/mod_define.c Thu Jan 1 01:00:00 1970 +++ apache_1.3.12.new/src/modules/extra/mod_define.c Thu Dec 30 22:00:58 1999 @@ -0,0 +1,416 @@ +/* +** mod_define.c - Apache module for configuration defines ($xxx) +** +** Copyright (c) 1998-2000 Ralf S. Engelschall +** Copyright (c) 1998-2000 Christian Reiber +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** 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. +*/ + +/* + * HISTORY + * + * v1.0: Originally written in December 1998 by + * Ralf S. Engelschall and + * Christian Reiber + * + * v1.1: Completely Overhauled in August 1999 by + * Ralf S. Engelschall + */ + +#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.12/src/modules/proxy/mod_proxy.c apache_1.3.12.new/src/modules/proxy/mod_proxy.c --- apache_1.3.12/src/modules/proxy/mod_proxy.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/modules/proxy/mod_proxy.c Mon Mar 13 19:30:30 2000 @@ -214,6 +214,9 @@ static int proxy_fixup(request_rec *r) { char *url, *p; +#ifdef EAPI + int rc; +#endif /* EAPI */ if (r->proxyreq == NOT_PROXY || 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) @@ -236,9 +247,44 @@ static void proxy_init(server_rec *r, pool *p) { ap_proxy_garbage_init(r, p); +#ifdef EAPI + ap_hook_use("ap::mod_proxy::init", + AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, r, p); +#endif } - +#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 +414,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 +431,9 @@ ents[i].port); else rc = DECLINED; +#ifdef EAPI + } +#endif /* EAPI */ /* an error or success */ if (rc != DECLINED && rc != HTTP_BAD_GATEWAY) @@ -390,6 +447,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) @@ -954,6 +1019,12 @@ 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.12/src/modules/proxy/proxy_http.c apache_1.3.12.new/src/modules/proxy/proxy_http.c --- apache_1.3.12/src/modules/proxy/proxy_http.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/modules/proxy/proxy_http.c Mon Mar 13 19:30:30 2000 @@ -189,6 +189,9 @@ const char *urlptr = NULL; const char *datestr; struct tbl_do_args tdo; +#ifdef EAPI + char *peer; +#endif void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -207,6 +210,12 @@ return HTTP_BAD_REQUEST; urlptr += 3; destport = DEFAULT_HTTP_PORT; +#ifdef EAPI + ap_hook_use("ap::mod_proxy::http::handler::set_destport", + AP_HOOK_SIG2(int,ptr), + AP_HOOK_TOPMOST, + &destport, r); +#endif /* EAPI */ strp = strchr(urlptr, '/'); if (strp == NULL) { desthost = ap_pstrdup(p, urlptr); @@ -243,12 +252,18 @@ err = ap_proxy_host2addr(proxyhost, &server_hp); if (err != NULL) return DECLINED; /* try another */ +#ifdef EAPI + peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport); +#endif } else { server.sin_port = htons(destport); err = ap_proxy_host2addr(desthost, &server_hp); if (err != NULL) return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); +#ifdef EAPI + peer = ap_psprintf(p, "%s:%u", desthost, destport); +#endif } sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -305,13 +320,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_SIG4(ptr,ptr,ptr,ptr), + AP_HOOK_DECLINE(NULL), + &errmsg, r, f, peer); + 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 && destport != 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.12/src/modules/standard/mod_log_config.c apache_1.3.12.new/src/modules/standard/mod_log_config.c --- apache_1.3.12/src/modules/standard/mod_log_config.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/modules/standard/mod_log_config.c Mon Mar 13 19:30:30 2000 @@ -257,6 +257,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; @@ -554,15 +557,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; } @@ -688,7 +712,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]; @@ -697,6 +725,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; @@ -758,6 +789,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.12/src/modules/standard/mod_rewrite.c apache_1.3.12.new/src/modules/standard/mod_rewrite.c --- apache_1.3.12/src/modules/standard/mod_rewrite.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/modules/standard/mod_rewrite.c Mon Mar 13 19:30:30 2000 @@ -3770,6 +3770,15 @@ } #endif /* ndef WIN32 && NETWARE*/ +#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.12/src/modules/standard/mod_so.c apache_1.3.12.new/src/modules/standard/mod_so.c --- apache_1.3.12/src/modules/standard/mod_so.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/modules/standard/mod_so.c Mon Mar 13 19:30:30 2000 @@ -257,11 +257,24 @@ * 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); } +#ifdef EAPI + if (modp->magic == MODULE_MAGIC_COOKIE_AP13) { + ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, NULL, + "Loaded DSO %s uses plain Apache 1.3 API, " + "this module might crash under EAPI! " + "(please recompile it with -DEAPI)", filename); + } +#endif /* * Add this module to the Apache core structures diff -Nru apache_1.3.12/src/modules/standard/mod_status.c apache_1.3.12.new/src/modules/standard/mod_status.c --- apache_1.3.12/src/modules/standard/mod_status.c Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/modules/standard/mod_status.c Mon Mar 13 19:30:30 2000 @@ -475,12 +475,33 @@ if (no_table_report) ap_rputs("


    Server Details

    \n\n", r); else +#ifndef NO_PRETTYPRINT + ap_rputs("

    \n\n" + "" + "" + "" + "" + "" +#ifndef NO_TIMES + "" +#endif + "" + "" + "" + "" + "" + "" + "" + "" + "\n", r); +#else /* NO_PRETTYPRINT */ #ifdef NO_TIMES /* Allow for OS/2 not having CPU stats */ ap_rputs("

    \n\n

    SrvPIDAccMCPUSSReqConnChildSlotHostVHostRequest
    \n\n", r); #else ap_rputs("

    \n\n

    SrvPIDAccM\nSSReqConnChildSlotClientVHostRequest
    \n\n", r); #endif +#endif /* NO_PRETTYPRINT */ } for (i = 0; i < HARD_SERVER_LIMIT; ++i) { @@ -598,14 +619,19 @@ vhost->server_hostname) : "(unavailable)"); } else { /* !no_table_report */ +#ifndef NO_PRETTYPRINT + ap_rprintf(r,""); +#else + ap_rprintf(r,""); +#endif if (score_record.status == SERVER_DEAD) ap_rprintf(r, - "\n\n"); else +#ifndef NO_PRETTYPRINT + ap_rprintf(r, + "\n\n", + score_record.client, + vhost ? vhost->server_hostname : "(unavailable)", + ap_escape_html(r->pool, score_record.request)); +#else ap_rprintf(r, "\n\n", ap_escape_html(r->pool, score_record.client), vhost ? ap_escape_html(r->pool, vhost->server_hostname) : "(unavailable)", ap_escape_html(r->pool, score_record.request)); +#endif } /* no_table_report */ } /* !short_report */ } /* if () */ @@ -708,6 +745,12 @@
    SrvPIDAccMCPU\nSSReqConnChildSlotClientVHostRequest
    %d-%d-%d/%lu/%lu", + "%d-%d-%d/%lu/%lu", i, (int) ps_record.generation, (int) conn_lres, my_lres, lres); else ap_rprintf(r, - "
    %d-%d%d%d/%lu/%lu", + "%d-%d%d%d/%lu/%lu", i, (int) ps_record.generation, (int) ps_record.pid, (int) conn_lres, my_lres, lres); @@ -665,12 +691,23 @@ ap_rprintf(r, "??..reading..
    %s" + "%s" + "%s" + "
    %s%s%s
    \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.12/src/support/apxs.pl apache_1.3.12.new/src/support/apxs.pl --- apache_1.3.12/src/support/apxs.pl Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/support/apxs.pl Mon Mar 13 19:30:30 2000 @@ -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.12/src/support/httpd.exp apache_1.3.12.new/src/support/httpd.exp --- apache_1.3.12/src/support/httpd.exp Mon Mar 13 19:38:44 2000 +++ apache_1.3.12.new/src/support/httpd.exp Mon Mar 13 19:30:30 2000 @@ -413,3 +413,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