From 423615a7dc4c56fa882372faae9d89aa0d088abe Mon Sep 17 00:00:00 2001 From: kloczek Date: Fri, 2 Feb 2001 09:09:51 +0000 Subject: [PATCH] some not includet (why ?) in eapi patches files neccessary during compile. Changed files: apache-EAPI-missing_files.patch -> 1.1 --- apache-EAPI-missing_files.patch | 2796 +++++++++++++++++++++++++++++++ 1 file changed, 2796 insertions(+) create mode 100644 apache-EAPI-missing_files.patch diff --git a/apache-EAPI-missing_files.patch b/apache-EAPI-missing_files.patch new file mode 100644 index 0000000..4d89471 --- /dev/null +++ b/apache-EAPI-missing_files.patch @@ -0,0 +1,2796 @@ +diff -Nru apache_1.3.17/src/include/ap_ctx.h apache_1.3.17.new/src/include/ap_ctx.h +--- apache_1.3.17/src/include/ap_ctx.h Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/src/include/ap_hook.h apache_1.3.17.new/src/include/ap_hook.h +--- apache_1.3.17/src/include/ap_hook.h Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/src/include/ap_mm.h apache_1.3.17.new/src/include/ap_mm.h +--- apache_1.3.17/src/include/ap_mm.h Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/htdocs/manual/mod/mod_define.html apache_1.3.17.new/htdocs/manual/mod/mod_define.html +--- apache_1.3.17/htdocs/manual/mod/mod_define.html Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/src/ap/ap_ctx.c apache_1.3.17.new/src/ap/ap_ctx.c +--- apache_1.3.17/src/ap/ap_ctx.c Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/src/ap/ap_hook.c apache_1.3.17.new/src/ap/ap_hook.c +--- apache_1.3.17/src/ap/ap_hook.c Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/src/ap/ap_mm.c apache_1.3.17.new/src/ap/ap_mm.c +--- apache_1.3.17/src/ap/ap_mm.c Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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.17/src/modules/extra/mod_define.c apache_1.3.17.new/src/modules/extra/mod_define.c +--- apache_1.3.17/src/modules/extra/mod_define.c Thu Jan 1 01:00:00 1970 ++++ apache_1.3.17.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 */ ++}; ++ -- 2.44.0