1 /* $OpenBSD: ap_hook.h,v 1.5 2005/03/28 23:26:51 niallo Exp $ */
2 
3 #if 0
4 =cut
5 #endif
6 /* ====================================================================
7  * Copyright (c) 1998-2000 The Apache Group.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the Apache Group
24  *    for use in the Apache HTTP server project (http://www.apache.org/)."
25  *
26  * 4. The names "Apache Server" and "Apache Group" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache"
32  *    nor may "Apache" appear in their names without prior written
33  *    permission of the Apache Group.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the Apache Group
38  *    for use in the Apache HTTP server project (http://www.apache.org/)."
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Apache Group and was originally based
56  * on public domain software written at the National Center for
57  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
58  * For more information on the Apache Group and the Apache HTTP server
59  * project, please see <http://www.apache.org/>.
60  *
61  */
62 
63 /*
64 **  Implementation of a Generic Hook Interface for Apache
65 **  Written by Ralf S. Engelschall <rse@engelschall.com>
66 **
67 **  See POD document at end of this file for description.
68 **  View it with the command ``pod2man ap_hook.h | nroff -man | more''
69 **
70 **  Attention: This header file is a little bit tricky.
71 **             It's a combination of a C source and an embedded POD document
72 **             The purpose of this is to have both things together at one
73 **             place. So you can both pass this file to the C compiler and
74 **             the pod2man translater.
75 */
76 
77 #ifndef AP_HOOK_H
78 #define AP_HOOK_H
79 
80 /*
81  * Function Signature Specification:
82  *
83  * We encode the complete signature ingredients as a bitfield
84  * stored in a single unsigned long integer value, which can be
85  * constructed with AP_HOOK_SIGx(...)
86  */
87 
88 /* the type of the signature bitfield */
89 typedef unsigned long int ap_hook_sig;
90 
91 /* the mask (bin) 111 (hex 0x7) for the triples in the bitfield */
92 #define AP_HOOK_SIG_TRIPLE_MASK  0x7
93 
94 /* the position of the triple */
95 #define AP_HOOK_SIG_TRIPLE_POS(n) ((n)*3)
96 
97 /* the constructor for triple #n with value v */
98 #define AP_HOOK_SIG_TRIPLE(n,v) \
99         (((ap_hook_sig)(v))<<((AP_HOOK_##n)*3))
100 
101 /* the check whether triple #n in sig contains value v */
102 #define AP_HOOK_SIG_HAS(sig,n,v) \
103         ((((ap_hook_sig)(sig))&AP_HOOK_SIG_TRIPLE(n, AP_HOOK_SIG_TRIPLE_MASK)) == (AP_HOOK_##n##_##v))
104 
105 /* utility function to get triple #n in sig */
106 #define AP_HOOK_SIG_TRIPLE_GET(sig,n) \
107         ((((ap_hook_sig)(sig))>>AP_HOOK_SIG_TRIPLE_POS(n))&(AP_HOOK_SIG_TRIPLE_MASK))
108 
109 /* utility function to set triple #n in sig to value v */
110 #define AP_HOOK_SIG_TRIPLE_SET(sig,n,v) \
111         ((((ap_hook_sig)(sig))&~(AP_HOOK_SIG_TRIPLE_MASK<<AP_HOOK_SIG_TRIPLE_POS(n)))|((v)<<AP_HOOK_SIG_TRIPLE_POS(n)))
112 
113 /* define the ingredients for the triple #0: id stuff */
114 #define AP_HOOK_ID          0
115 #define AP_HOOK_ID_ok       AP_HOOK_SIG_TRIPLE(ID,0)
116 #define AP_HOOK_ID_undef    AP_HOOK_SIG_TRIPLE(ID,1)
117 
118 /* define the ingredients for the triple #1: return code */
119 #define AP_HOOK_RC          1
120 #define AP_HOOK_RC_void     AP_HOOK_SIG_TRIPLE(RC,0)
121 #define AP_HOOK_RC_char     AP_HOOK_SIG_TRIPLE(RC,1)
122 #define AP_HOOK_RC_int      AP_HOOK_SIG_TRIPLE(RC,2)
123 #define AP_HOOK_RC_long     AP_HOOK_SIG_TRIPLE(RC,3)
124 #define AP_HOOK_RC_float    AP_HOOK_SIG_TRIPLE(RC,4)
125 #define AP_HOOK_RC_double   AP_HOOK_SIG_TRIPLE(RC,5)
126 #define AP_HOOK_RC_ptr      AP_HOOK_SIG_TRIPLE(RC,6)
127 
128 /* define the ingredients for the triple #2: argument 1 */
129 #define AP_HOOK_A1          2
130 #define AP_HOOK_A1_ctx      AP_HOOK_SIG_TRIPLE(A1,0)
131 #define AP_HOOK_A1_char     AP_HOOK_SIG_TRIPLE(A1,1)
132 #define AP_HOOK_A1_int      AP_HOOK_SIG_TRIPLE(A1,2)
133 #define AP_HOOK_A1_long     AP_HOOK_SIG_TRIPLE(A1,3)
134 #define AP_HOOK_A1_float    AP_HOOK_SIG_TRIPLE(A1,4)
135 #define AP_HOOK_A1_double   AP_HOOK_SIG_TRIPLE(A1,5)
136 #define AP_HOOK_A1_ptr      AP_HOOK_SIG_TRIPLE(A1,6)
137 
138 /* define the ingredients for the triple #3: argument 2 */
139 #define AP_HOOK_A2          3
140 #define AP_HOOK_A2_ctx      AP_HOOK_SIG_TRIPLE(A2,0)
141 #define AP_HOOK_A2_char     AP_HOOK_SIG_TRIPLE(A2,1)
142 #define AP_HOOK_A2_int      AP_HOOK_SIG_TRIPLE(A2,2)
143 #define AP_HOOK_A2_long     AP_HOOK_SIG_TRIPLE(A2,3)
144 #define AP_HOOK_A2_float    AP_HOOK_SIG_TRIPLE(A2,4)
145 #define AP_HOOK_A2_double   AP_HOOK_SIG_TRIPLE(A2,5)
146 #define AP_HOOK_A2_ptr      AP_HOOK_SIG_TRIPLE(A2,6)
147 
148 /* define the ingredients for the triple #4: argument 3 */
149 #define AP_HOOK_A3          4
150 #define AP_HOOK_A3_ctx      AP_HOOK_SIG_TRIPLE(A3,0)
151 #define AP_HOOK_A3_char     AP_HOOK_SIG_TRIPLE(A3,1)
152 #define AP_HOOK_A3_int      AP_HOOK_SIG_TRIPLE(A3,2)
153 #define AP_HOOK_A3_long     AP_HOOK_SIG_TRIPLE(A3,3)
154 #define AP_HOOK_A3_float    AP_HOOK_SIG_TRIPLE(A3,4)
155 #define AP_HOOK_A3_double   AP_HOOK_SIG_TRIPLE(A3,5)
156 #define AP_HOOK_A3_ptr      AP_HOOK_SIG_TRIPLE(A3,6)
157 
158 /* define the ingredients for the triple #5: argument 4 */
159 #define AP_HOOK_A4          5
160 #define AP_HOOK_A4_ctx      AP_HOOK_SIG_TRIPLE(A4,0)
161 #define AP_HOOK_A4_char     AP_HOOK_SIG_TRIPLE(A4,1)
162 #define AP_HOOK_A4_int      AP_HOOK_SIG_TRIPLE(A4,2)
163 #define AP_HOOK_A4_long     AP_HOOK_SIG_TRIPLE(A4,3)
164 #define AP_HOOK_A4_float    AP_HOOK_SIG_TRIPLE(A4,4)
165 #define AP_HOOK_A4_double   AP_HOOK_SIG_TRIPLE(A4,5)
166 #define AP_HOOK_A4_ptr      AP_HOOK_SIG_TRIPLE(A4,6)
167 
168 /* define the ingredients for the triple #6: argument 5 */
169 #define AP_HOOK_A5          6
170 #define AP_HOOK_A5_ctx      AP_HOOK_SIG_TRIPLE(A5,0)
171 #define AP_HOOK_A5_char     AP_HOOK_SIG_TRIPLE(A5,1)
172 #define AP_HOOK_A5_int      AP_HOOK_SIG_TRIPLE(A5,2)
173 #define AP_HOOK_A5_long     AP_HOOK_SIG_TRIPLE(A5,3)
174 #define AP_HOOK_A5_float    AP_HOOK_SIG_TRIPLE(A5,4)
175 #define AP_HOOK_A5_double   AP_HOOK_SIG_TRIPLE(A5,5)
176 #define AP_HOOK_A5_ptr      AP_HOOK_SIG_TRIPLE(A5,6)
177 
178 /* define the ingredients for the triple #7: argument 6 */
179 #define AP_HOOK_A6          7
180 #define AP_HOOK_A6_ctx      AP_HOOK_SIG_TRIPLE(A6,0)
181 #define AP_HOOK_A6_char     AP_HOOK_SIG_TRIPLE(A6,1)
182 #define AP_HOOK_A6_int      AP_HOOK_SIG_TRIPLE(A6,2)
183 #define AP_HOOK_A6_long     AP_HOOK_SIG_TRIPLE(A6,3)
184 #define AP_HOOK_A6_float    AP_HOOK_SIG_TRIPLE(A6,4)
185 #define AP_HOOK_A6_double   AP_HOOK_SIG_TRIPLE(A6,5)
186 #define AP_HOOK_A6_ptr      AP_HOOK_SIG_TRIPLE(A6,6)
187 
188 /* define the ingredients for the triple #8: argument 7 */
189 #define AP_HOOK_A7          8
190 #define AP_HOOK_A7_ctx      AP_HOOK_SIG_TRIPLE(A7,0)
191 #define AP_HOOK_A7_char     AP_HOOK_SIG_TRIPLE(A7,1)
192 #define AP_HOOK_A7_int      AP_HOOK_SIG_TRIPLE(A7,2)
193 #define AP_HOOK_A7_long     AP_HOOK_SIG_TRIPLE(A7,3)
194 #define AP_HOOK_A7_float    AP_HOOK_SIG_TRIPLE(A7,4)
195 #define AP_HOOK_A7_double   AP_HOOK_SIG_TRIPLE(A7,5)
196 #define AP_HOOK_A7_ptr      AP_HOOK_SIG_TRIPLE(A7,6)
197 
198 /* define the ingredients for the triple #9: argument 8 */
199 #define AP_HOOK_A8          9
200 #define AP_HOOK_A8_ctx      AP_HOOK_SIG_TRIPLE(9,0)
201 #define AP_HOOK_A8_char     AP_HOOK_SIG_TRIPLE(9,1)
202 #define AP_HOOK_A8_int      AP_HOOK_SIG_TRIPLE(9,2)
203 #define AP_HOOK_A8_long     AP_HOOK_SIG_TRIPLE(9,3)
204 #define AP_HOOK_A8_float    AP_HOOK_SIG_TRIPLE(9,4)
205 #define AP_HOOK_A8_double   AP_HOOK_SIG_TRIPLE(9,5)
206 #define AP_HOOK_A8_ptr      AP_HOOK_SIG_TRIPLE(9,6)
207 
208 /* the constructor for unknown signatures */
209 #define AP_HOOK_SIG_UNKNOWN AP_HOOK_ID_undef
210 
211 /* the constructor for signatures with 1 type */
212 #define AP_HOOK_SIG1(rc) \
213         (AP_HOOK_RC_##rc)
214 
215 /* the constructor for signatures with 2 types */
216 #define AP_HOOK_SIG2(rc,a1) \
217         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1)
218 
219 /* the constructor for signatures with 3 types */
220 #define AP_HOOK_SIG3(rc,a1,a2) \
221         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2)
222 
223 /* the constructor for signatures with 4 types */
224 #define AP_HOOK_SIG4(rc,a1,a2,a3) \
225         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3)
226 
227 /* the constructor for signatures with 5 types */
228 #define AP_HOOK_SIG5(rc,a1,a2,a3,a4) \
229         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4)
230 
231 /* the constructor for signatures with 6 types */
232 #define AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5) \
233         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5)
234 
235 /* the constructor for signatures with 7 types */
236 #define AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6) \
237         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6)
238 
239 /* the constructor for signatures with 8 types */
240 #define AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7) \
241         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6|AP_HOOK_A7_##a7)
242 
243 /* the constructor for signatures with 9 types */
244 #define AP_HOOK_SIG9(rc,a1,a2,a3,a4,a5,a6,a7,a8) \
245         (AP_HOOK_RC_##rc|AP_HOOK_A1_##a1|AP_HOOK_A2_##a2|AP_HOOK_A3_##a3|AP_HOOK_A4_##a4|AP_HOOK_A5_##a5|AP_HOOK_A6_##a6|AP_HOOK_A7_##a7|AP_HOOK_A8_##a8)
246 
247 /*
248  * Return Value Mode Identification
249  */
250 
251 /* the type of the return value modes */
252 typedef unsigned int ap_hook_mode;
253 
254 /* the mode of the return value */
255 #define AP_HOOK_MODE_UNKNOWN  0
256 #define AP_HOOK_MODE_TOPMOST  1
257 #define AP_HOOK_MODE_DECLINE  2
258 #define AP_HOOK_MODE_DECLTMP  3
259 #define AP_HOOK_MODE_ALL      4
260 
261 /* the constructors for the return value modes */
262 #define AP_HOOK_TOPMOST       AP_HOOK_MODE_TOPMOST
263 #define AP_HOOK_DECLINE(val)  AP_HOOK_MODE_DECLINE, (val)
264 #define AP_HOOK_DECLTMP(val)  AP_HOOK_MODE_DECLTMP, (val)
265 #define AP_HOOK_ALL           AP_HOOK_MODE_ALL
266 
267 /*
268  * Hook State Identification
269  */
270 
271 /* the type of the hook state */
272 typedef unsigned short int ap_hook_state;
273 
274 /* the values of the hook state */
275 #define AP_HOOK_STATE_UNDEF       0
276 #define AP_HOOK_STATE_NOTEXISTANT 1
277 #define AP_HOOK_STATE_ESTABLISHED 2
278 #define AP_HOOK_STATE_CONFIGURED  3
279 #define AP_HOOK_STATE_REGISTERED  4
280 
281 /*
282  * Hook Context Identification
283  *
284  * Notice: Null is ok here, because AP_HOOK_NOCTX is just a dummy argument
285  *         because we know from the signature whether the argument is a
286  *         context value or just the dummy value.
287  */
288 
289 #define AP_HOOK_NOCTX  (void *)(0)
290 #define AP_HOOK_CTX(v) (void *)(v)
291 
292 /*
293  * Internal Hook Record Definition
294  */
295 
296 /* the union holding the arbitrary decline values */
297 typedef union {
298 	char   v_char;
299 	int    v_int;
300 	long   v_long;
301 	float  v_float;
302 	double v_double;
303 	void  *v_ptr;
304 } ap_hook_value;
305 
306 /* the structure holding one hook function and its context */
307 typedef struct {
308 	void *hf_ptr;              /* function pointer       */
309 	void *hf_ctx;              /* function context       */
310 } ap_hook_func;
311 
312 /* the structure holding one hook entry with all its registered functions */
313 typedef struct {
314 	char          *he_hook;    /* hook name (=unique id) */
315 	ap_hook_sig    he_sig;     /* hook signature         */
316 	int            he_modeid;  /* hook mode id           */
317 	ap_hook_value  he_modeval; /* hook mode value        */
318 	ap_hook_func **he_func;    /* hook registered funcs  */
319 } ap_hook_entry;
320 
321 /* the maximum number of hooks and functions per hook */
322 #define AP_HOOK_MAX_ENTRIES 512
323 #define AP_HOOK_MAX_FUNCS   128
324 
325 /*
326  * Extended Variable Argument (vararg) Support
327  *
328  * In ANSI C varargs exists, but because the prototypes of function with
329  * varargs cannot reflect the types of the varargs, K&R argument passing
330  * conventions have to apply for the compiler.  This means mainly a conversion
331  * of shorter type variants to the maximum variant (according to sizeof). The
332  * above va_type() macro provides this mapping from the wanted types to the
333  * physically used ones.
334  */
335 
336 /* the mapping */
337 #define VA_TYPE_char   int
338 #define VA_TYPE_short  int
339 #define VA_TYPE_int    int
340 #define VA_TYPE_long   long
341 #define VA_TYPE_float  double
342 #define VA_TYPE_double double
343 #define VA_TYPE_ptr    void *
344 #define VA_TYPE_ctx    void *
345 
346 /* the constructor */
347 #ifdef  va_type
348 #undef  va_type
349 #endif
350 #define va_type(type)  VA_TYPE_ ## type
351 
352 /*
353  * Miscellaneous stuff
354  */
355 
356 #ifndef FALSE
357 #define FALSE 0
358 #define TRUE  !FALSE
359 #endif
360 
361 /*
362  * Wrapper macros for the callback-function register/unregister calls.
363  *
364  * Background: Strict ANSI C doesn't allow a function pointer to be treated as
365  * a void pointer on argument passing, but we cannot declare the argument as a
366  * function prototype, because the functions can have arbitrary signatures. So
367  * we have to use a void pointer here. But to not require explicit casts on
368  * function pointers for every register/unregister call, we smooth the API a
369  * little bit by providing these macros.
370  */
371 
372 #define ap_hook_register(hook,func,ctx) ap_hook_register_I(hook,(void *)(func),ctx)
373 #define ap_hook_unregister(hook,func)   ap_hook_unregister_I(hook,(void *)(func))
374 
375 /*
376  * Prototypes for the hook API functions
377  */
378 
379 API_EXPORT(void)          ap_hook_init         (void);
380 API_EXPORT(void)          ap_hook_kill         (void);
381 API_EXPORT(int)           ap_hook_configure    (char *hook, ap_hook_sig sig,
382     ap_hook_mode modeid, ...);
383 API_EXPORT(int)           ap_hook_register_I   (char *hook, void *func,
384     void *ctx);
385 API_EXPORT(int)           ap_hook_unregister_I (char *hook, void *func);
386 API_EXPORT(ap_hook_state) ap_hook_status       (char *hook);
387 API_EXPORT(int)           ap_hook_use          (char *hook, ap_hook_sig sig,
388     ap_hook_mode modeid, ...);
389 API_EXPORT(int)           ap_hook_call         (char *hook, ...);
390 
391 #endif /* AP_HOOK_H */
392 
393 /*
394 =pod
395 ##
396 ##  Embedded POD document
397 ##
398 
399 =head1 NAME
400 
401 B<ap_hook> - B<Generic Hook Interface for Apache>
402 
403 =head1 SYNOPSIS
404 
405 B<Hook Library Setup:>
406 
407  void ap_hook_init(void);
408  void ap_hook_kill(void);
409 
410 B<Hook Configuration and Registration:>
411 
412  int ap_hook_configure(char *hook, ap_hook_sig sig, ap_hook_mode mode);
413  int ap_hook_register(char *hook, void *func, void *ctx);
414  int ap_hook_unregister(char *hook, void *func);
415 
416 B<Hook Usage:>
417 
418  ap_hook_state ap_hook_status(char *hook);
419  int ap_hook_use(char *hook, ap_hook_sig sig, ap_hook_mode mode, ...);
420  int ap_hook_call(char *hook, ...);
421 
422 B<Hook Signature Constructors> (ap_hook_sig):
423 
424  AP_HOOK_SIG1(rc)
425  AP_HOOK_SIG2(rc,a1)
426  AP_HOOK_SIG3(rc,a1,a2)
427  AP_HOOK_SIG4(rc,a1,a2,a3)
428  AP_HOOK_SIG5(rc,a1,a2,a3,a4)
429  AP_HOOK_SIG6(rc,a1,a2,a3,a4,a5)
430  AP_HOOK_SIG7(rc,a1,a2,a3,a4,a5,a6)
431  AP_HOOK_SIG8(rc,a1,a2,a3,a4,a5,a6,a7)
432 
433 B<Hook Modes Constructors> (ap_hook_mode):
434 
435  AP_HOOK_TOPMOST
436  AP_HOOK_DECLINE(value)
437  AP_HOOK_DECLTMP(value)
438  AP_HOOK_ALL
439 
440 B<Hook States> (ap_hook_state):
441 
442  AP_HOOK_STATE_UNDEF
443  AP_HOOK_STATE_NOTEXISTANT
444  AP_HOOK_STATE_ESTABLISHED
445  AP_HOOK_STATE_CONFIGURED
446  AP_HOOK_STATE_REGISTERED
447 
448 =head1 DESCRIPTION
449 
450 This library implements a generic hook interface for Apache which can be used
451 to loosely couple code through arbitrary hooks. There are two use cases for
452 this mechanism:
453 
454 =over 3
455 
456 =item B<1. Extension and Overrides>
457 
458 Inside a specific code section you want to perform a specific function call
459 for extension reasons.  But you want to allow one or more modules to implement
460 this function by registering hooks. Those hooks are registered on a stack and
461 can be even configured to have a I<decline> return value. As long as there are
462 functions which return the decline value the next function on the stack is
463 tried. When the first function doesn't return the decline value the hook call
464 stops.
465 
466 The original intent of this use case is to provide a flexible extension
467 mechanism where modules can override functionality.
468 
469 =item B<2. Intercommunication>
470 
471 Inside a specific code you have a function you want to export. But you first
472 want to allow other code to override this function.  And second you want to
473 export this function without real object file symbol references. Instead you
474 want to register the function and let the users call this function by name.
475 
476 The original intent of this use case is to allow inter-module communication
477 without direct symbol references, which are a big I<no-no> for the I<Dynamic
478 Shared Object> (DSO) situation.
479 
480 =back
481 
482 And the following design goals existed:
483 
484 =over 3
485 
486 =item B<1. Minimum code changes>
487 
488 The hook calls should look very similar to the corresponding direct function
489 call to allow one to easily translate it. And the total amount of changes for
490 the hook registration, hook configuration and hook usage should be as small as
491 possible to minimize the total code changes. Additionally a shorthand API
492 function (ap_hook_use) should be provided which lets one trivially add a hook
493 by just changing the code at a single location.
494 
495 =item B<2. The hook call has to be maximum flexible>
496 
497 In order to avoid nasty hacks, maximum flexiblity for the hook calls is
498 needed, i.e. any function signature (the set of types for the return value and
499 the arguments) should be supported.  And it should be possible to
500 register always a context (ctx) variable with a function which is passed to
501 the corresponding function when the hook call is performed.
502 
503 =back
504 
505 The implementation of this library directly followed these two design goals.
506 
507 =head1 USAGE
508 
509 Using this hook API is a four-step process:
510 
511 =over 3
512 
513 =item B<1. Initialization>
514 
515 Initialize or destroy the hook mechanism inside your application program:
516 
517  ap_hook_init();
518     :
519  ap_hook_kill();
520 
521 =item B<2. Configuration>
522 
523 Configure a particular hook by specifing its name, signature and return type
524 semantic:
525 
526  ap_hook_configure("lookup", AP_HOOK_SIG2(ptr,ptr,ctx), AP_HOOK_DECLINE(NULL));
527  ap_hook_configure("setup", AP_HOOK_SIG2(int,ptr,char), AP_HOOK_DECLTMP(FALSE));
528  ap_hook_configure("read", AP_HOOK_SIG2(void,ptr), AP_HOOK_TOPMOST);
529  ap_hook_configure("logit", AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL);
530 
531 This configures four hooks:
532 
533 A hook named C<lookup> with the signature C<void *lookup(void *, void *)>
534 (where the second argument is C<NULL> or the private context pointer of the
535 hook function which can be optionally provided at the registration step
536 later) and a return code semantic which says: Proceed as long as the
537 registered lookup functions return C<NULL> or no more registered functions
538 exists. A call for this hook has to provide 2 argument only (a pointer to the
539 return variable and the first argument), because the context is
540 implicitly provided by the hook mechanism. Sample idea: I<The first function
541 who was successful in looking up a variable provides the value>.
542 
543 A hook named C<setup> with the signature C<int setup(void *, char)" and a
544 return code semantic equal to the one of the C<lookup> hook. But the decline
545 return value is implemented by a temporay variable of the hook mechanism and
546 only used for the decline decision. So a call to this hook has to provide 2
547 arguments only (the first and second argument, but no address to a return
548 value). Sample idea: I<Any function can handle the setup and when one
549 function handled it stops the processing by indicating this with the return
550 value>.
551 
552 A hook named C<read> with the signature C<void read(void *)> and a return code
553 semantic which says: Only the top most function on the registered function
554 stack is tried (and independet of a possible return value in non-void
555 context). A call to this hook has to provide exactly 1 argument (the
556 single argument to the hook function). Sample idea: I<We want to
557 use a read function and allow others to override it, but independent how much
558 registered functions exists, only top most (= last registered) function
559 overrides and is used>.
560 
561 A hook named C<logit> with the signature C<void logit(void *)> and a return
562 code semantic which says: All registered functions on the hook functioin stack
563 are tried. Sample idea: I<We pass a FILE pointer to the logging functions and
564 any function can log whatever it wants>.
565 
566 =item B<3. Registration>
567 
568 Register the actual functions which should be used by the hook:
569 
570  ap_hook_register("lookup", mylookup, mycontext);
571  ap_hook_register("setup", mysetup);
572  ap_hook_register("read", myread);
573  ap_hook_register("logit", mylogit);
574 
575 This registers the function C<mylookup()> under the C<lookup> hook with the
576 private context given by the variable C<mycontext>. And it registers the
577 function C<mysetup()> under the C<setup> hook without any context. Same for
578 C<myread> and C<mylogit>.
579 
580 =item B<4. Usage>
581 
582 Finally use the hooks, i.e. instead of using direct function calls like
583 
584  rc = mylookup(a1, a2);
585  rc = mysetup(a1, a2);
586  myread(a1);
587  mylogit(a1);
588 
589 you now use:
590 
591  ap_hook_call("lookup", &rc, a1, a2);
592  ap_hook_call("setup", &rc, a1, a2);
593  ap_hook_call("read", a1);
594  ap_hook_call("logit", a1);
595 
596 which are internally translated to:
597 
598  rc = mylookup(a1, a2, mycontext);
599  rc = mysetup(a1, a2);
600  myread(a1);
601  mylogit(a1);
602 
603 Notice two things here: First the context (C<mycontext>) for the C<mylookup()>
604 function is automatically added by the hook mechanism. And it is a different
605 (and not fixed) context for each registered function, of course.  Second,
606 return values always have to be pushed into variables and a pointer to them
607 has to be given as the second argument to C<ap_hook_call> (except for
608 functions which have a void return type, of course).
609 
610 BTW, the return value of C<ap_hook_call()> is always C<TRUE> or C<FALSE>.
611 C<TRUE> when at least one function call was successful (always the case for
612 C<AP_HOOK_TOPMOST> and C<AP_HOOK_ALL>). C<FALSE> when all functions
613 returned the decline value or no functions are registered at all.
614 
615 =back
616 
617 =head1 RESTRICTIONS
618 
619 To make the hook implementation efficient and to not bloat up the code too
620 much a few restrictions have to make:
621 
622 =over 3
623 
624 =item 1.
625 
626 Only function calls with up to 4 arguments are implemented. When more are
627 needed you can either extend the hook implementation by using more bits for
628 the signature configuration or you can do a workaround when the function is
629 your own one: Put the remaining (N-4-1) arguments into a structure and pass
630 only a pointer (one argument) as the forth argument.
631 
632 =item 2.
633 
634 Only the following ANSI C variable types are supported:
635 
636  - For the return value:
637    void (= none), char, int, float, double, ptr (= void *)
638  - For the arguments:
639    ctx  (= context), char, int, float, double, ptr (= void *)
640 
641 This means in theory that 6^5 (=7776) signature combinations are possible. But
642 because we don't need all of them inside Apache and it would bloat up the code
643 too dramatically we implement only a subset of those combinations. The
644 implemented signatures can be specified inside C<ap_hook.c> and the
645 corresponding code can be automatically generated by running ``C<perl
646 ap_hook.c>'' (yeah, no joke ;-).  So when you need a hook with a different
647 still not implemented signature you either have to again use a workaround as
648 above (i.e. use a structure) or just add the signature to the C<ap_hook.c>
649 file.
650 
651 =head1 EXAMPLE
652 
653 We want to call `C<ssize_t read(int, void *, size_t)>' through hooks in order
654 to allow modules to override this call.  So, somewhere we have a replacement
655 function for C<read()> defined (same signature, of course):
656 
657  ssize_t my_read(int, void *, size_t);
658 
659 We now configure a C<read> hook. Here the C<AP_HOOK_SIGx()> macro defines the
660 signature of the C<read()>-like callback functions and has to match the
661 prototype of C<read()>. But we have to replace typedefs with the physical
662 underlaying ANSI C types. And C<AP_HOOK_DECLINE()> sets the return value of
663 the read()-like functions which forces the next hook to be called (here -1).
664 And we register the original C<read()> function as the default hook.
665 
666  ap_hook_configure("read",
667                    AP_HOOK_SIG4(int,int,ptr,int),
668                    AP_HOOK_DECLINE(-1));
669  ap_hook_register("read", read);
670 
671 Now a module wants to override the C<read()> call and registers the
672 C<my_read()> function:
673 
674  ap_hook_register("read", my_read);
675 
676 The function logically gets pushed onto a stack, so the execution order is the
677 reverse registering order, i.e. I<last registered - first called>. Now we can
678 replace the standard C<read()> call
679 
680  bytes = read(fd, buf, bufsize);
681  if (bytes == -1)
682     ...error...
683 
684 with the hook based call:
685 
686   rc = ap_hook_call("read", &bytes, fd, buf, bufsize);
687   if (rc == FALSE)
688      ...error...
689 
690 Now internally the following is done: The call `C<bytes = my_read(fd, buf,
691 bufsize)>' is done. When it returns not -1 (the decline value) nothing
692 more is done. But when C<my_read()> returns -1 the next function is tried:
693 `C<bytes = read(fd, buf, bufsize)>'. When this one also returns -1 you get
694 `rc == FALSE'. When it finally returns not -1 you get `rc == TRUE'.
695 
696 =head1 SEE ALSO
697 
698 ap_ctx(3)
699 
700 =head1 HISTORY
701 
702 The ap_hook(3) interface was originally designed and
703 implemented in October 1998 by Ralf S. Engelschall.
704 
705 =head1 AUTHOR
706 
707  Ralf S. Engelschall
708  rse@engelschall.com
709  www.engelschall.com
710 
711 =cut
712 */
713