apr_hooks.h revision 262253
1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef APR_HOOKS_H 18#define APR_HOOKS_H 19 20#include "apu.h" 21/* For apr_array_header_t */ 22#include "apr_tables.h" 23 24/** 25 * @file apr_hooks.h 26 * @brief Apache hook functions 27 */ 28 29#ifdef __cplusplus 30extern "C" { 31#endif 32/** 33 * @defgroup APR_Util_Hook Hook Functions 34 * @ingroup APR_Util 35 * @{ 36 */ 37 38/** 39 * @defgroup apr_hook_probes Hook probe capability 40 * APR hooks provide a trace probe capability for capturing 41 * the flow of control and return values with hooks. 42 * 43 * In order to use this facility, the application must define 44 * the symbol APR_HOOK_PROBES_ENABLED and the four APR_HOOK_PROBE_ 45 * macros described below before including apr_hooks.h in files 46 * that use the APR_IMPLEMENT_EXTERNAL_HOOK_* macros. 47 * 48 * This probe facility is not provided for APR optional hooks. 49 * @{ 50 */ 51 52#ifdef APR_HOOK_PROBES_ENABLED 53#define APR_HOOK_INT_DCL_UD void *ud = NULL 54#else 55/** internal implementation detail to avoid the ud declaration when 56 * hook probes are not used 57 */ 58#define APR_HOOK_INT_DCL_UD 59/** 60 * User-defined hook probe macro that is invoked when the hook 61 * is run, before calling any hook functions. 62 * @param ud A void * user data field that should be filled in by 63 * this macro, and will be provided to the other hook probe macros. 64 * @param ns The namespace prefix of the hook functions 65 * @param name The name of the hook 66 * @param args The argument list to the hook functions, with enclosing 67 * parens. 68 */ 69#define APR_HOOK_PROBE_ENTRY(ud,ns,name,args) 70/** 71 * User-defined hook probe macro that is invoked after the hook 72 * has run. 73 * @param ud A void * user data field that was filled in by the user- 74 * provided APR_HOOK_PROBE_ENTRY(). 75 * @param ns The namespace prefix of the hook functions 76 * @param name The name of the hook 77 * @param rv The return value of the hook, or 0 if the hook is void. 78 * @param args The argument list to the hook functions, with enclosing 79 * parens. 80 */ 81#define APR_HOOK_PROBE_RETURN(ud,ns,name,rv,args) 82/** 83 * User-defined hook probe macro that is invoked before calling a 84 * hook function. 85 * @param ud A void * user data field that was filled in by the user- 86 * provided APR_HOOK_PROBE_ENTRY(). 87 * @param ns The namespace prefix of the hook functions 88 * @param name The name of the hook 89 * @param src The value of apr_hook_debug_current at the time the function 90 * was hooked (usually the source file implementing the hook function). 91 * @param args The argument list to the hook functions, with enclosing 92 * parens. 93 */ 94#define APR_HOOK_PROBE_INVOKE(ud,ns,name,src,args) 95/** 96 * User-defined hook probe macro that is invoked after calling a 97 * hook function. 98 * @param ud A void * user data field that was filled in by the user- 99 * provided APR_HOOK_PROBE_ENTRY(). 100 * @param ns The namespace prefix of the hook functions 101 * @param name The name of the hook 102 * @param src The value of apr_hook_debug_current at the time the function 103 * was hooked (usually the source file implementing the hook function). 104 * @param rv The return value of the hook function, or 0 if the hook is void. 105 * @param args The argument list to the hook functions, with enclosing 106 * parens. 107 */ 108#define APR_HOOK_PROBE_COMPLETE(ud,ns,name,src,rv,args) 109#endif 110 111/** @} */ 112 113/** macro to return the prototype of the hook function */ 114#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \ 115link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void) 116 117/** macro to declare the hook correctly */ 118#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \ 119typedef ret ns##_HOOK_##name##_t args; \ 120link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \ 121 const char * const *aszPre, \ 122 const char * const *aszSucc, int nOrder); \ 123link##_DECLARE(ret) ns##_run_##name args; \ 124APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \ 125typedef struct ns##_LINK_##name##_t \ 126 { \ 127 ns##_HOOK_##name##_t *pFunc; \ 128 const char *szName; \ 129 const char * const *aszPredecessors; \ 130 const char * const *aszSuccessors; \ 131 int nOrder; \ 132 } ns##_LINK_##name##_t; 133 134/** macro to declare the hook structure */ 135#define APR_HOOK_STRUCT(members) \ 136static struct { members } _hooks; 137 138/** macro to link the hook structure */ 139#define APR_HOOK_LINK(name) \ 140 apr_array_header_t *link_##name; 141 142/** macro to implement the hook */ 143#define APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \ 144link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf,const char * const *aszPre, \ 145 const char * const *aszSucc,int nOrder) \ 146 { \ 147 ns##_LINK_##name##_t *pHook; \ 148 if(!_hooks.link_##name) \ 149 { \ 150 _hooks.link_##name=apr_array_make(apr_hook_global_pool,1,sizeof(ns##_LINK_##name##_t)); \ 151 apr_hook_sort_register(#name,&_hooks.link_##name); \ 152 } \ 153 pHook=apr_array_push(_hooks.link_##name); \ 154 pHook->pFunc=pf; \ 155 pHook->aszPredecessors=aszPre; \ 156 pHook->aszSuccessors=aszSucc; \ 157 pHook->nOrder=nOrder; \ 158 pHook->szName=apr_hook_debug_current; \ 159 if(apr_hook_debug_enabled) \ 160 apr_hook_debug_show(#name,aszPre,aszSucc); \ 161 } \ 162 APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \ 163 { \ 164 return _hooks.link_##name; \ 165 } 166 167/** 168 * Implement a hook that has no return code, and therefore runs all of the 169 * registered functions 170 * @param ns The namespace prefix of the hook functions 171 * @param link The linkage declaration prefix of the hook 172 * @param name The name of the hook 173 * @param args_decl The declaration of the arguments for the hook 174 * @param args_use The names for the arguments for the hook 175 * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which 176 * provide export linkage from the module that IMPLEMENTs the hook, and 177 * import linkage from external modules that link to the hook's module. 178 */ 179#define APR_IMPLEMENT_EXTERNAL_HOOK_VOID(ns,link,name,args_decl,args_use) \ 180APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \ 181link##_DECLARE(void) ns##_run_##name args_decl \ 182 { \ 183 ns##_LINK_##name##_t *pHook; \ 184 int n; \ 185 APR_HOOK_INT_DCL_UD; \ 186\ 187 APR_HOOK_PROBE_ENTRY(ud, ns, name, args_use); \ 188\ 189 if(_hooks.link_##name) \ 190 { \ 191 pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \ 192 for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \ 193 { \ 194 APR_HOOK_PROBE_INVOKE(ud, ns, name, (char *)pHook[n].szName, args_use); \ 195 pHook[n].pFunc args_use; \ 196 APR_HOOK_PROBE_COMPLETE(ud, ns, name, (char *)pHook[n].szName, 0, args_use); \ 197 } \ 198 } \ 199\ 200 APR_HOOK_PROBE_RETURN(ud, ns, name, 0, args_use); \ 201\ 202 } 203 204/* FIXME: note that this returns ok when nothing is run. I suspect it should 205 really return decline, but that breaks Apache currently - Ben 206*/ 207/** 208 * Implement a hook that runs until one of the functions returns something 209 * other than OK or DECLINE 210 * @param ns The namespace prefix of the hook functions 211 * @param link The linkage declaration prefix of the hook 212 * @param ret Type to return 213 * @param name The name of the hook 214 * @param args_decl The declaration of the arguments for the hook 215 * @param args_use The names for the arguments for the hook 216 * @param ok Success value 217 * @param decline Decline value 218 * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which 219 * provide export linkage from the module that IMPLEMENTs the hook, and 220 * import linkage from external modules that link to the hook's module. 221 */ 222#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,args_use,ok,decline) \ 223APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \ 224link##_DECLARE(ret) ns##_run_##name args_decl \ 225 { \ 226 ns##_LINK_##name##_t *pHook; \ 227 int n; \ 228 ret rv = ok; \ 229 APR_HOOK_INT_DCL_UD; \ 230\ 231 APR_HOOK_PROBE_ENTRY(ud, ns, name, args_use); \ 232\ 233 if(_hooks.link_##name) \ 234 { \ 235 pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \ 236 for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \ 237 { \ 238 APR_HOOK_PROBE_INVOKE(ud, ns, name, (char *)pHook[n].szName, args_use); \ 239 rv=pHook[n].pFunc args_use; \ 240 APR_HOOK_PROBE_COMPLETE(ud, ns, name, (char *)pHook[n].szName, rv, args_use); \ 241 if(rv != ok && rv != decline) \ 242 break; \ 243 rv = ok; \ 244 } \ 245 } \ 246\ 247 APR_HOOK_PROBE_RETURN(ud, ns, name, rv, args_use); \ 248\ 249 return rv; \ 250 } 251 252 253/** 254 * Implement a hook that runs until the first function returns something 255 * other than the value of decline 256 * @param ns The namespace prefix of the hook functions 257 * @param link The linkage declaration prefix of the hook 258 * @param name The name of the hook 259 * @param ret Type to return 260 * @param args_decl The declaration of the arguments for the hook 261 * @param args_use The names for the arguments for the hook 262 * @param decline Decline value 263 * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which 264 * provide export linkage from the module that IMPLEMENTs the hook, and 265 * import linkage from external modules that link to the hook's module. 266 */ 267#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ns,link,ret,name,args_decl,args_use,decline) \ 268APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \ 269link##_DECLARE(ret) ns##_run_##name args_decl \ 270 { \ 271 ns##_LINK_##name##_t *pHook; \ 272 int n; \ 273 ret rv = decline; \ 274 APR_HOOK_INT_DCL_UD; \ 275\ 276 APR_HOOK_PROBE_ENTRY(ud, ns, name, args_use); \ 277\ 278 if(_hooks.link_##name) \ 279 { \ 280 pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \ 281 for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \ 282 { \ 283 APR_HOOK_PROBE_INVOKE(ud, ns, name, (char *)pHook[n].szName, args_use); \ 284 rv=pHook[n].pFunc args_use; \ 285 APR_HOOK_PROBE_COMPLETE(ud, ns, name, (char *)pHook[n].szName, rv, args_use); \ 286\ 287 if(rv != decline) \ 288 break; \ 289 } \ 290 } \ 291\ 292 APR_HOOK_PROBE_RETURN(ud, ns, name, rv, args_use); \ 293\ 294 return rv; \ 295 } 296 297 /* Hook orderings */ 298/** run this hook first, before ANYTHING */ 299#define APR_HOOK_REALLY_FIRST (-10) 300/** run this hook first */ 301#define APR_HOOK_FIRST 0 302/** run this hook somewhere */ 303#define APR_HOOK_MIDDLE 10 304/** run this hook after every other hook which is defined*/ 305#define APR_HOOK_LAST 20 306/** run this hook last, after EVERYTHING */ 307#define APR_HOOK_REALLY_LAST 30 308 309/** 310 * The global pool used to allocate any memory needed by the hooks. 311 */ 312APU_DECLARE_DATA extern apr_pool_t *apr_hook_global_pool; 313 314/** 315 * A global variable to determine if debugging information about the 316 * hooks functions should be printed. 317 */ 318APU_DECLARE_DATA extern int apr_hook_debug_enabled; 319 320/** 321 * The name of the module that is currently registering a function. 322 */ 323APU_DECLARE_DATA extern const char *apr_hook_debug_current; 324 325/** 326 * Register a hook function to be sorted. 327 * @param szHookName The name of the Hook the function is registered for 328 * @param aHooks The array which stores all of the functions for this hook 329 */ 330APU_DECLARE(void) apr_hook_sort_register(const char *szHookName, 331 apr_array_header_t **aHooks); 332/** 333 * Sort all of the registered functions for a given hook. 334 */ 335APU_DECLARE(void) apr_hook_sort_all(void); 336 337/** 338 * Print all of the information about the current hook. This is used for 339 * debugging purposes. 340 * @param szName The name of the hook 341 * @param aszPre All of the functions in the predecessor array 342 * @param aszSucc All of the functions in the successor array 343 */ 344APU_DECLARE(void) apr_hook_debug_show(const char *szName, 345 const char * const *aszPre, 346 const char * const *aszSucc); 347 348/** 349 * Remove all currently registered functions. 350 */ 351APU_DECLARE(void) apr_hook_deregister_all(void); 352 353/** @} */ 354#ifdef __cplusplus 355} 356#endif 357 358#endif /* APR_HOOKS_H */ 359