ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hybrid-ircservices-1/modules.c
(Generate patch)

Comparing hybrid-ircservices-1/modules.c (file contents):
Revision 1201 by michael, Mon Aug 22 18:55:33 2011 UTC vs.
Revision 1209 by michael, Thu Aug 25 19:05:49 2011 UTC

# Line 21 | Line 21
21  
22   /* Internal structure for callbacks. */
23   typedef struct callbackinfo_ CallbackInfo;
24 < struct callbackinfo_ {
25 <    char *name;
26 <    int calling;  /* used by {call,remove}_callback() for safe callback
27 <                   * removal from inside the callback */
28 <    struct {
29 <        callback_t func;
30 <        const Module *adder;
31 <        int pri;
32 <    } *funcs;
33 <    int funcs_count;
24 > struct callbackinfo_
25 > {
26 >  char *name;
27 >  int calling;                  /* used by {call,remove}_callback() for safe callback
28 >                                 * removal from inside the callback */
29 >  struct
30 >  {
31 >    callback_t func;
32 >    const Module *adder;
33 >    int pri;
34 >  } *funcs;
35 >  int funcs_count;
36   };
37  
38   /* Structure for module data. */
39 < struct Module_ {
40 <    Module *next, *prev;
41 <    char *name;                 /* Module name (path passed to load_module())*/
42 <    ConfigDirective *modconfig; /* `module_config' in this module */
43 <    Module ***this_module_pptr; /* `_this_module_ptr' in this module */
44 <    const int32 *module_version_ptr;  /* `module_version' in this module */
45 <    void *dllhandle;            /* Handle used by dynamic linker */
46 <    CallbackInfo *callbacks;
47 <    int callbacks_count;
48 <    const Module **users;       /* Array of module's users (use_module()) */
49 <    int users_count;
39 > struct Module_
40 > {
41 >  Module *next, *prev;
42 >  char *name;                   /* Module name (path passed to load_module()) */
43 >  ConfigDirective *modconfig;   /* `module_config' in this module */
44 >  Module ***this_module_pptr;   /* `_this_module_ptr' in this module */
45 >  const int32 *module_version_ptr;      /* `module_version' in this module */
46 >  void *dllhandle;              /* Handle used by dynamic linker */
47 >  CallbackInfo *callbacks;
48 >  int callbacks_count;
49 >  const Module **users;         /* Array of module's users (use_module()) */
50 >  int users_count;
51   };
52  
53  
54   /* Module data for Services core. */
55 < static Module coremodule = {.name = "core"};
55 > static Module coremodule = {.name = "core" };
56  
57  
58   /* Global list of modules. */
# Line 67 | Line 70 | static int cb_reconfigure = -1;
70   #if STATIC_MODULES
71  
72   /* Structure for a module symbol. */
73 < struct modsym {
74 <    const char *symname;
75 <    void *value;
73 > struct modsym
74 > {
75 >  const char *symname;
76 >  void *value;
77   };
78  
79   /* Static module information (from modules/modules.a): */
80 < struct modinfo {
81 <    const char *modname;
82 <    struct modsym *modsyms;
80 > struct modinfo
81 > {
82 >  const char *modname;
83 >  struct modsym *modsyms;
84   };
85   extern struct modinfo modlist[];
86  
87 < #else  /* !STATIC_MODULES */
87 > #else /* !STATIC_MODULES */
88  
89   static void *program_handle;    /* Handle for the main program */
90  
91 < #endif  /* STATIC_MODULES */
91 > #endif /* STATIC_MODULES */
92  
93   /*************************************************************************/
94  
95   /* Internal routine declarations: */
96  
97   static Module *internal_load_module(const char *modulename);
98 < static int internal_init_module(Module *module);
99 < static int internal_unload_module(Module *module, int shutdown);
98 > static int internal_init_module(Module * module);
99 > static int internal_unload_module(Module * module, int shutdown);
100  
101   /*************************************************************************/
102  
# Line 124 | Line 129 | static int internal_unload_module(Module
129   /********************* Initialization and cleanup ************************/
130   /*************************************************************************/
131  
132 < int modules_init(int ac, char **av)
132 > int
133 > modules_init(int ac, char **av)
134   {
135   #if !STATIC_MODULES
136 <    program_handle = dlopen(NULL, 0);
136 >  program_handle = dlopen(NULL, 0);
137   #endif
138 <    cb_load_module   = register_callback("load module");
139 <    cb_unload_module = register_callback("unload module");
140 <    cb_reconfigure   = register_callback("reconfigure");
141 <    if (cb_load_module < 0 || cb_unload_module < 0 || cb_reconfigure < 0) {
142 <        log("modules_init: register_callback() failed\n");
143 <        return 0;
144 <    }
145 <    return 1;
138 >  cb_load_module = register_callback("load module");
139 >  cb_unload_module = register_callback("unload module");
140 >  cb_reconfigure = register_callback("reconfigure");
141 >  if (cb_load_module < 0 || cb_unload_module < 0 || cb_reconfigure < 0)
142 >  {
143 >    log("modules_init: register_callback() failed\n");
144 >    return 0;
145 >  }
146 >  return 1;
147   }
148  
149   /*************************************************************************/
150  
151 < void modules_cleanup(void)
151 > void
152 > modules_cleanup(void)
153   {
154 <    int i;
154 >  int i;
155  
156 <    unload_all_modules();
157 <    unregister_callback(cb_reconfigure);
158 <    unregister_callback(cb_unload_module);
159 <    unregister_callback(cb_load_module);
160 <    ARRAY_FOREACH(i, coremodule.callbacks) {
161 <        if (coremodule.callbacks[i].name) {
162 <            log("modules: Core forgot to unregister callback `%s'",
163 <                coremodule.callbacks[i].name);
164 <            free(coremodule.callbacks[i].name);
165 <            free(coremodule.callbacks[i].funcs);
166 <        }
156 >  unload_all_modules();
157 >  unregister_callback(cb_reconfigure);
158 >  unregister_callback(cb_unload_module);
159 >  unregister_callback(cb_load_module);
160 >  ARRAY_FOREACH(i, coremodule.callbacks)
161 >  {
162 >    if (coremodule.callbacks[i].name)
163 >    {
164 >      log("modules: Core forgot to unregister callback `%s'",
165 >          coremodule.callbacks[i].name);
166 >      free(coremodule.callbacks[i].name);
167 >      free(coremodule.callbacks[i].funcs);
168      }
169 <    free(coremodule.callbacks);
169 >  }
170 >  free(coremodule.callbacks);
171   }
172  
173   /*************************************************************************/
174  
175 < void unload_all_modules(void)
175 > void
176 > unload_all_modules(void)
177   {
178 <    /* Normally it would be sufficient to iterate through the module list,
179 <     * since new modules are always inserted at the front of the list, but
180 <     * it is possible for an older module to lock a newer module via the
181 <     * "load module" callback, resulting in unload failures if that simple
182 <     * method was used.  Instead, we repeatedly search the module list for
183 <     * the first unloadable module (a module that is not the core module
184 <     * and is not locked), unload that module, and repeat until no
185 <     * unloadable modules are left.  (In theory, since a module's locks are
186 <     * forcibly when the module is unloaded, this should only leave the
187 <     * core module, but we check anyway just to be safe.) */
188 <
189 <    for (;;) {
190 <        Module *mod;
191 <        LIST_FOREACH (mod, modulelist) {
192 <            if (strcmp(mod->name, "core") != 0) {
193 <                int i;
194 <                ARRAY_FOREACH (i, mod->users) {
195 <                    if (mod->users[i] != mod)
196 <                        break;
197 <                }
198 <                if (i >= mod->users_count) {
199 <                    /* This module has no users (except possibly itself),
189 <                     * so unload it */
190 <                    break;
191 <                }
192 <            }
193 <        }
194 <        if (!mod)
178 >  /* Normally it would be sufficient to iterate through the module list,
179 >   * since new modules are always inserted at the front of the list, but
180 >   * it is possible for an older module to lock a newer module via the
181 >   * "load module" callback, resulting in unload failures if that simple
182 >   * method was used.  Instead, we repeatedly search the module list for
183 >   * the first unloadable module (a module that is not the core module
184 >   * and is not locked), unload that module, and repeat until no
185 >   * unloadable modules are left.  (In theory, since a module's locks are
186 >   * forcibly when the module is unloaded, this should only leave the
187 >   * core module, but we check anyway just to be safe.) */
188 >
189 >  for (;;)
190 >  {
191 >    Module *mod;
192 >    LIST_FOREACH(mod, modulelist)
193 >    {
194 >      if (strcmp(mod->name, "core") != 0)
195 >      {
196 >        int i;
197 >        ARRAY_FOREACH(i, mod->users)
198 >        {
199 >          if (mod->users[i] != mod)
200              break;
196        if (!internal_unload_module(mod, 1)) {
197            log("modules: Failed to unload `%s' on exit", mod->name);
198            /* Unlink it anyway, but don't free the structure to avoid
199             * segfaults in the module.  This is an impossible case
200             * anyway, so we don't worry about the leak. */
201            LIST_REMOVE(mod, modulelist);
201          }
202 <    }
203 <
204 <    if (!modulelist) {
205 <        log("modules: BUG: core module got removed from module list during"
206 <            " shutdown!");
208 <    } else if (modulelist != &coremodule || modulelist->next != NULL) {
209 <        Module *mod;
210 <        log("modules: BUG: failed to unload some modules during shutdown"
211 <            " (circular lock?)");
212 <        LIST_FOREACH (mod, modulelist) {
213 <            if (strcmp(mod->name, "core") != 0) {
214 <                log("modules: -- module %s not unloaded", mod->name);
215 <            }
202 >        if (i >= mod->users_count)
203 >        {
204 >          /* This module has no users (except possibly itself),
205 >           * so unload it */
206 >          break;
207          }
208 +      }
209      }
210 +    if (!mod)
211 +      break;
212 +    if (!internal_unload_module(mod, 1))
213 +    {
214 +      log("modules: Failed to unload `%s' on exit", mod->name);
215 +      /* Unlink it anyway, but don't free the structure to avoid
216 +       * segfaults in the module.  This is an impossible case
217 +       * anyway, so we don't worry about the leak. */
218 +      LIST_REMOVE(mod, modulelist);
219 +    }
220 +  }
221 +
222 +  if (!modulelist)
223 +  {
224 +    log("modules: BUG: core module got removed from module list during"
225 +        " shutdown!");
226 +  }
227 +  else if (modulelist != &coremodule || modulelist->next != NULL)
228 +  {
229 +    Module *mod;
230 +    log("modules: BUG: failed to unload some modules during shutdown"
231 +        " (circular lock?)");
232 +    LIST_FOREACH(mod, modulelist)
233 +    {
234 +      if (strcmp(mod->name, "core") != 0)
235 +      {
236 +        log("modules: -- module %s not unloaded", mod->name);
237 +      }
238 +    }
239 +  }
240   }
241  
242   /*************************************************************************/
# Line 234 | Line 256 | static const char *dl_last_error;
256  
257   /* Low-level routine to open a module and return a handle. */
258  
259 < static void *my_dlopen(const char *name)
259 > static void *
260 > my_dlopen(const char *name)
261   {
262   #if !STATIC_MODULES
263  
264 <    char pathname[PATH_MAX+1];
265 <    snprintf(pathname, sizeof(pathname), "%s/modules/%s.so",
266 <             services_dir, name);
267 <    return dlopen(pathname, RTLD_NOW | RTLD_GLOBAL);
268 <
269 < #else  /* STATIC_MODULES */
270 <
271 <    int i;
272 <
273 <    for (i = 0; modlist[i].modname; i++) {
274 <        if (strcmp(modlist[i].modname, name) == 0)
275 <            break;
276 <    }
277 <    if (!modlist[i].modname) {
278 <        dl_last_error = "Module not found";
279 <        return NULL;
280 <    }
281 <    return &modlist[i];
264 >  char pathname[PATH_MAX + 1];
265 >  snprintf(pathname, sizeof(pathname), "%s/modules/%s.so",
266 >           services_dir, name);
267 >  return dlopen(pathname, RTLD_NOW | RTLD_GLOBAL);
268 >
269 > #else /* STATIC_MODULES */
270 >
271 >  int i;
272 >
273 >  for (i = 0; modlist[i].modname; i++)
274 >  {
275 >    if (strcmp(modlist[i].modname, name) == 0)
276 >      break;
277 >  }
278 >  if (!modlist[i].modname)
279 >  {
280 >    dl_last_error = "Module not found";
281 >    return NULL;
282 >  }
283 >  return &modlist[i];
284  
285   #endif /* STATIC_MODULES */
286 < } /* my_dlopen() */
286 > }                               /* my_dlopen() */
287  
288   /*************************************************************************/
289  
290   /* Low-level routine to close a module. */
291  
292 < static void my_dlclose(void *handle)
292 > static void
293 > my_dlclose(void *handle)
294   {
295   #if !STATIC_MODULES
296  
297 <    dlclose(handle);
297 >  dlclose(handle);
298  
299 < #else  /* STATIC_MODULES */
299 > #else /* STATIC_MODULES */
300  
301 <    /* nothing */
301 >  /* nothing */
302  
303   #endif /* STATIC_MODULES */
304 < } /* my_dlclose() */
304 > }                               /* my_dlclose() */
305  
306   /*************************************************************************/
307  
308   /* Low-level routine to retrieve a symbol from a module given its handle. */
309  
310 < static void *my_dlsym(void *handle, const char *symname)
310 > static void *
311 > my_dlsym(void *handle, const char *symname)
312   {
313   #if !STATIC_MODULES
314  
315   # if SYMS_NEED_UNDERSCORES
316 <    char buf[256];
317 <    if (strlen(symname) > sizeof(buf)-2) {  /* too long for buffer */
318 <        log("modules: symbol name too long in my_dlsym(): %s", symname);
319 <        return NULL;
320 <    }
321 <    snprintf(buf, sizeof(buf), "_%s", symname);
322 <    symname = buf;
316 >  char buf[256];
317 >  if (strlen(symname) > sizeof(buf) - 2)
318 >  {                             /* too long for buffer */
319 >    log("modules: symbol name too long in my_dlsym(): %s", symname);
320 >    return NULL;
321 >  }
322 >  snprintf(buf, sizeof(buf), "_%s", symname);
323 >  symname = buf;
324   # endif
325 <    if (handle) {
326 <        return dlsym(handle, symname);
327 <    } else {
328 <        Module *mod;
329 <        void *ptr;
330 <        LIST_FOREACH (mod, modulelist) {
331 <            ptr = dlsym(mod->dllhandle?mod->dllhandle:program_handle, symname);
332 <            if (ptr)
333 <                return ptr;
334 <        }
335 <        return NULL;
325 >  if (handle)
326 >  {
327 >    return dlsym(handle, symname);
328 >  }
329 >  else
330 >  {
331 >    Module *mod;
332 >    void *ptr;
333 >    LIST_FOREACH(mod, modulelist)
334 >    {
335 >      ptr = dlsym(mod->dllhandle ? mod->dllhandle : program_handle, symname);
336 >      if (ptr)
337 >        return ptr;
338      }
339 +    return NULL;
340 +  }
341  
342 < #else  /* STATIC_MODULES */
342 > #else /* STATIC_MODULES */
343  
344 <    int i;
344 >  int i;
345  
346 <    if (handle) {
347 <        struct modsym *syms = ((struct modinfo *)handle)->modsyms;
348 <        for (i = 0; syms[i].symname; i++) {
349 <            if (strcmp(syms[i].symname, symname) == 0)
350 <                break;
351 <        }
352 <        if (!syms[i].symname) {
353 <            dl_last_error = "Symbol not found";
354 <            return NULL;
355 <        }
356 <        return syms[i].value;
357 <    } else {
358 <        const char *save_dl_last_error = dl_last_error;
359 <        for (i = 0; modlist[i].modname; i++) {
360 <            void *value = my_dlsym(&modlist[i], symname);
361 <            if (value) {
362 <                dl_last_error = save_dl_last_error;
363 <                return value;
364 <            }
365 <        }
366 <        dl_last_error = "Symbol not found";
367 <        return NULL;
346 >  if (handle)
347 >  {
348 >    struct modsym *syms = ((struct modinfo *) handle)->modsyms;
349 >    for (i = 0; syms[i].symname; i++)
350 >    {
351 >      if (strcmp(syms[i].symname, symname) == 0)
352 >        break;
353 >    }
354 >    if (!syms[i].symname)
355 >    {
356 >      dl_last_error = "Symbol not found";
357 >      return NULL;
358 >    }
359 >    return syms[i].value;
360 >  }
361 >  else
362 >  {
363 >    const char *save_dl_last_error = dl_last_error;
364 >    for (i = 0; modlist[i].modname; i++)
365 >    {
366 >      void *value = my_dlsym(&modlist[i], symname);
367 >      if (value)
368 >      {
369 >        dl_last_error = save_dl_last_error;
370 >        return value;
371 >      }
372      }
373 +    dl_last_error = "Symbol not found";
374 +    return NULL;
375 +  }
376  
377   #endif /* STATIC_MODULES */
378 < } /* my_dlsym() */
378 > }                               /* my_dlsym() */
379  
380   /*************************************************************************/
381  
382   /* Low-level routine to return the error message (if any) from the previous
383   * call. */
384  
385 < static const char *my_dlerror(void)
385 > static const char *
386 > my_dlerror(void)
387   {
388   #if !STATIC_MODULES
389  
390 <    return dlerror();
390 >  return dlerror();
391  
392 < #else  /* STATIC_MODULES */
392 > #else /* STATIC_MODULES */
393  
394 <    const char *str = dl_last_error;
395 <    dl_last_error = NULL;
396 <    return str;
394 >  const char *str = dl_last_error;
395 >  dl_last_error = NULL;
396 >  return str;
397  
398   #endif /* STATIC_MODULES */
399 < } /* my_dlerror() */
399 > }                               /* my_dlerror() */
400  
401   /*************************************************************************/
402   /************************ Module-level functions *************************/
# Line 366 | Line 406 | static const char *my_dlerror(void)
406   * (External interface to the above functions.)
407   */
408  
409 < Module *load_module(const char *modulename)
409 > Module *
410 > load_module(const char *modulename)
411   {
412 <    Module *module;
412 >  Module *module;
413  
414  
415 <    if (!modulename) {
416 <        log("load_module(): modulename is NULL!");
417 <        return NULL;
418 <    }
419 <
379 <    log_debug(1, "Loading module `%s'", modulename);
415 >  if (!modulename)
416 >  {
417 >    log("load_module(): modulename is NULL!");
418 >    return NULL;
419 >  }
420  
421 <    module = internal_load_module(modulename);
382 <    if (!module)
383 <        return NULL;
384 <    LIST_INSERT(module, modulelist);
421 >  log_debug(1, "Loading module `%s'", modulename);
422  
423 <    if (!configure(module->name, module->modconfig,
424 <                   CONFIGURE_READ | CONFIGURE_SET)) {
425 <        log("modules: configure() failed for %s", modulename);
426 <        goto fail;
390 <    }
423 >  module = internal_load_module(modulename);
424 >  if (!module)
425 >    return NULL;
426 >  LIST_INSERT(module, modulelist);
427  
428 <    if (!internal_init_module(module)) {
429 <        log("modules: init_module() failed for %s", modulename);
430 <        deconfigure(module->modconfig);
431 <        goto fail;
432 <    }
428 >  if (!configure(module->name, module->modconfig,
429 >                 CONFIGURE_READ | CONFIGURE_SET))
430 >  {
431 >    log("modules: configure() failed for %s", modulename);
432 >    goto fail;
433 >  }
434 >
435 >  if (!internal_init_module(module))
436 >  {
437 >    log("modules: init_module() failed for %s", modulename);
438 >    deconfigure(module->modconfig);
439 >    goto fail;
440 >  }
441  
442 <    log_debug(1, "Successfully loaded module `%s'", modulename);
443 <    call_callback_2(cb_load_module, module, module->name);
442 >  log_debug(1, "Successfully loaded module `%s'", modulename);
443 >  call_callback_2(cb_load_module, module, module->name);
444  
445 <    /* This is a REALLY STUPID HACK to ensure protocol modules are loaded
446 <     * first--but hey, it works! */
447 <    if (protocol_features & PF_UNSET) {
448 <        log("FATAL: load_module(): A protocol module must be loaded first!");
449 <        unload_module(module);
450 <        return NULL;
451 <    }
445 >  /* This is a REALLY STUPID HACK to ensure protocol modules are loaded
446 >   * first--but hey, it works! */
447 >  if (protocol_features & PF_UNSET)
448 >  {
449 >    log("FATAL: load_module(): A protocol module must be loaded first!");
450 >    unload_module(module);
451 >    return NULL;
452 >  }
453  
454 <    return module;
454 >  return module;
455  
456 <  fail:
457 <    free(module->name);
458 <    my_dlclose(module->dllhandle);
459 <    LIST_REMOVE(module, modulelist);
460 <    free(module);
461 <    return NULL;
456 > fail:
457 >  free(module->name);
458 >  my_dlclose(module->dllhandle);
459 >  LIST_REMOVE(module, modulelist);
460 >  free(module);
461 >  return NULL;
462   }
463  
464   /************************************/
# Line 422 | Line 467 | Module *load_module(const char *modulena
467   * on error.
468   */
469  
470 < static Module *internal_load_module(const char *modulename)
470 > static Module *
471 > internal_load_module(const char *modulename)
472   {
473 <    void *handle;
474 <    Module *module, *mptr;
475 <    int32 *verptr;
476 <    Module ***thisptr;
477 <    ConfigDirective *confptr;
478 <
479 <    if (strstr(modulename, "../")) {
480 <        log("modules: Attempt to load bad module name: %s", modulename);
481 <        goto err_return;
482 <    }
483 <    LIST_SEARCH(modulelist, name, modulename, strcmp, mptr);
484 <    if (mptr) {
485 <        log("modules: Attempt to load module `%s' twice", modulename);
486 <        goto err_return;
487 <    }
488 <
489 <    handle = my_dlopen(modulename);
490 <    if (!handle) {
491 <        const char *error = my_dlerror();
492 <        if (!error)
493 <            error = "Unknown error";
494 <        log("modules: Unable to load module `%s': %s", modulename, error);
495 <        goto err_return;
496 <    }
497 <
498 <    module = scalloc(sizeof(*module), 1);
499 <    module->dllhandle = handle;
500 <    module->name = sstrdup(modulename);
501 <
502 <    thisptr = NULL;
503 <    if (check_module_symbol(module, "_this_module_ptr", (void **)&thisptr,
504 <                            NULL)){
473 >  void *handle;
474 >  Module *module, *mptr;
475 >  int32 *verptr;
476 >  Module ***thisptr;
477 >  ConfigDirective *confptr;
478 >
479 >  if (strstr(modulename, "../"))
480 >  {
481 >    log("modules: Attempt to load bad module name: %s", modulename);
482 >    goto err_return;
483 >  }
484 >  LIST_SEARCH(modulelist, name, modulename, strcmp, mptr);
485 >  if (mptr)
486 >  {
487 >    log("modules: Attempt to load module `%s' twice", modulename);
488 >    goto err_return;
489 >  }
490 >
491 >  handle = my_dlopen(modulename);
492 >  if (!handle)
493 >  {
494 >    const char *error = my_dlerror();
495 >    if (!error)
496 >      error = "Unknown error";
497 >    log("modules: Unable to load module `%s': %s", modulename, error);
498 >    goto err_return;
499 >  }
500 >
501 >  module = scalloc(sizeof(*module), 1);
502 >  module->dllhandle = handle;
503 >  module->name = sstrdup(modulename);
504 >
505 >  thisptr = NULL;
506 >  if (check_module_symbol(module, "_this_module_ptr", (void **) &thisptr,
507 >                          NULL))
508 >  {
509   #if !defined(STATIC_MODULES)
510 <        /* When using dynamic linking, the above may return the first
511 <         * instance of `_this_module_ptr' found in _any_ module (though
512 <         * giving priority to the given module), so we need to check if
513 <         * we've seen this address before.  With static linking, the result
514 <         * will be NULL if the symbol does not exist in this specific
515 <         * module, so the extra check is unnecessary. */
516 <        LIST_SEARCH_SCALAR(modulelist, this_module_pptr, thisptr, mptr);
517 <        if (mptr)
518 <            thisptr = NULL;
510 >    /* When using dynamic linking, the above may return the first
511 >     * instance of `_this_module_ptr' found in _any_ module (though
512 >     * giving priority to the given module), so we need to check if
513 >     * we've seen this address before.  With static linking, the result
514 >     * will be NULL if the symbol does not exist in this specific
515 >     * module, so the extra check is unnecessary. */
516 >    LIST_SEARCH_SCALAR(modulelist, this_module_pptr, thisptr, mptr);
517 >    if (mptr)
518 >      thisptr = NULL;
519   #endif
520 <    }
521 <    if (!thisptr) {
522 <        log("modules: Unable to load module `%s': No `_this_module_ptr' symbol"
523 <            " found", modulename);
524 <        goto err_freemod;
525 <    }
526 <    module->this_module_pptr = thisptr;
527 <    **thisptr = module;
528 <
529 <    verptr = NULL;  /* as above */
530 <    if (check_module_symbol(module, "module_version", (void **)&verptr, NULL)){
520 >  }
521 >  if (!thisptr)
522 >  {
523 >    log("modules: Unable to load module `%s': No `_this_module_ptr' symbol"
524 >        " found", modulename);
525 >    goto err_freemod;
526 >  }
527 >  module->this_module_pptr = thisptr;
528 >  **thisptr = module;
529 >
530 >  verptr = NULL;                /* as above */
531 >  if (check_module_symbol(module, "module_version", (void **) &verptr, NULL))
532 >  {
533   #if !defined(STATIC_MODULES)
534 <        LIST_SEARCH_SCALAR(modulelist, module_version_ptr, verptr, mptr);
535 <        if (mptr)
536 <            verptr = NULL;
534 >    LIST_SEARCH_SCALAR(modulelist, module_version_ptr, verptr, mptr);
535 >    if (mptr)
536 >      verptr = NULL;
537   #endif
538 <    }
539 <    if (!verptr) {
540 <        log("modules: Unable to load module `%s': No `module_version'"
541 <            " symbol found", modulename);
542 <        goto err_freemod;
543 <    } else if (*verptr != MODULE_VERSION_CODE) {
544 <        log("modules: Unable to load module `%s': Version mismatch"
545 <            " (module version = %08X, core version = %08X)",
546 <            modulename, *verptr, MODULE_VERSION_CODE);
547 <        goto err_freemod;
548 <    }
549 <    module->module_version_ptr = verptr;
550 <
551 <    confptr = NULL;  /* as above */
552 <    if (check_module_symbol(module, "module_config", (void **)&confptr, NULL)){
538 >  }
539 >  if (!verptr)
540 >  {
541 >    log("modules: Unable to load module `%s': No `module_version'"
542 >        " symbol found", modulename);
543 >    goto err_freemod;
544 >  }
545 >  else if (*verptr != MODULE_VERSION_CODE)
546 >  {
547 >    log("modules: Unable to load module `%s': Version mismatch"
548 >        " (module version = %08X, core version = %08X)",
549 >        modulename, *verptr, MODULE_VERSION_CODE);
550 >    goto err_freemod;
551 >  }
552 >  module->module_version_ptr = verptr;
553 >
554 >  confptr = NULL;               /* as above */
555 >  if (check_module_symbol(module, "module_config", (void **) &confptr, NULL))
556 >  {
557   #if !defined(STATIC_MODULES)
558 <        LIST_SEARCH_SCALAR(modulelist, modconfig, confptr, mptr);
559 <        if (mptr)
560 <            confptr = NULL;
558 >    LIST_SEARCH_SCALAR(modulelist, modconfig, confptr, mptr);
559 >    if (mptr)
560 >      confptr = NULL;
561   #endif
562 <    }
563 <    module->modconfig = confptr;
562 >  }
563 >  module->modconfig = confptr;
564  
565 <    return module;
565 >  return module;
566  
567 <  err_freemod:
568 <    free(module->name);
569 <    free(module);
570 <    my_dlclose(handle);
571 <  err_return:
572 <    return NULL;
567 > err_freemod:
568 >  free(module->name);
569 >  free(module);
570 >  my_dlclose(handle);
571 > err_return:
572 >  return NULL;
573   }
574  
575   /************************************/
# Line 522 | Line 578 | static Module *internal_load_module(cons
578   * 1 if the module does not have an init_module() function.
579   */
580  
581 < static int internal_init_module(Module *module)
581 > static int
582 > internal_init_module(Module * module)
583   {
584 <    int (*initfunc)(void);
584 >  int (*initfunc) (void);
585  
586 <    initfunc = get_module_symbol(module, "init_module");
587 <    if (initfunc)
588 <        return initfunc();
589 <    else
590 <        return 1;
586 >  initfunc = get_module_symbol(module, "init_module");
587 >  if (initfunc)
588 >    return initfunc();
589 >  else
590 >    return 1;
591   }
592  
593   /*************************************************************************/
# Line 539 | Line 596 | static int internal_init_module(Module *
596   * failure.
597   */
598  
599 < int unload_module(Module *module)
599 > int
600 > unload_module(Module * module)
601   {
602 <    return internal_unload_module(module, 0);
602 >  return internal_unload_module(module, 0);
603   }
604  
605   /************************************/
# Line 551 | Line 609 | int unload_module(Module *module)
609   * or not.
610   */
611  
612 < static int internal_unload_module(Module *module, int shutdown)
612 > static int
613 > internal_unload_module(Module * module, int shutdown)
614   {
615 <    int (*exit_module)(int shutdown);
616 <    Module *tmp;
617 <    int i;
615 >  int (*exit_module) (int shutdown);
616 >  Module *tmp;
617 >  int i;
618  
619  
620 <    if (!module) {
621 <        log("unload_module(): module is NULL!");
622 <        return 0;
623 <    }
620 >  if (!module)
621 >  {
622 >    log("unload_module(): module is NULL!");
623 >    return 0;
624 >  }
625  
626 <    if (module->users_count > 0) {
627 <        log("modules: Attempt to unload in-use module `%s' (in use by %s%s)",
628 <            module->name, module->users[0]->name,
629 <            module->users_count>1 ? " and others" : "");
630 <        return 0;
631 <    }
626 >  if (module->users_count > 0)
627 >  {
628 >    log("modules: Attempt to unload in-use module `%s' (in use by %s%s)",
629 >        module->name, module->users[0]->name,
630 >        module->users_count > 1 ? " and others" : "");
631 >    return 0;
632 >  }
633  
634 <    log_debug(1, "Unloading module `%s'", module->name);
634 >  log_debug(1, "Unloading module `%s'", module->name);
635  
636 <    /* Call the module's exit routine */
637 <    exit_module = get_module_symbol(module, "exit_module");
638 <    if (exit_module && !(*exit_module)(shutdown)) {
639 <        if (shutdown) {
640 <            log("modules: exit_module() for module `%s' returned zero on"
641 <                " shutdown, unloading module anyway", module->name);
642 <        } else {
643 <            return 0;
583 <        }
636 >  /* Call the module's exit routine */
637 >  exit_module = get_module_symbol(module, "exit_module");
638 >  if (exit_module && !(*exit_module) (shutdown))
639 >  {
640 >    if (shutdown)
641 >    {
642 >      log("modules: exit_module() for module `%s' returned zero on"
643 >          " shutdown, unloading module anyway", module->name);
644      }
645 <
646 <    /* Remove the module from the global module list, ensuring that no
647 <     * new callbacks or the like can be added while we unload it */
588 <    LIST_REMOVE(module, modulelist);
589 <
590 <    /* Ensure that callbacks and use_module() calls are properly undone */
591 <    LIST_FOREACH (tmp, modulelist) {
592 <        ARRAY_FOREACH (i, tmp->users) {
593 <            if (tmp->users[i] == module) {
594 <                log("modules: Module `%s' forgot to unuse_module() for"
595 <                    " module `%s'", module->name, tmp->name);
596 <                ARRAY_REMOVE(tmp->users, i);
597 <                i--;
598 <            }
599 <        }
600 <        ARRAY_FOREACH (i, tmp->callbacks) {
601 <            int j;
602 <            /* Don't warn for callbacks that couldn't have been removed
603 <             * because the callback was in use (e.g. for shutting down
604 <             * after a crash) */
605 <            if (tmp->callbacks[i].calling)
606 <                continue;
607 <            ARRAY_FOREACH (j, tmp->callbacks[i].funcs) {
608 <                if (tmp->callbacks[i].funcs[j].adder == module) {
609 <                    log("modules: Module `%s' forgot to remove callback"
610 <                        " `%s' from module `%s'", module->name,
611 <                        tmp->callbacks[i].name, tmp->name);
612 <                    ARRAY_REMOVE(tmp->callbacks[i].funcs, j);
613 <                    j--;
614 <                }
615 <            }
616 <        }
645 >    else
646 >    {
647 >      return 0;
648      }
649 <    ARRAY_FOREACH (i, module->callbacks) {
650 <        if (module->callbacks[i].name) {
651 <            log("modules: Module `%s' forgot to unregister callback `%s'",
652 <                module->name, module->callbacks[i].name);
653 <            free(module->callbacks[i].name);
654 <            free(module->callbacks[i].funcs);
649 >  }
650 >
651 >  /* Remove the module from the global module list, ensuring that no
652 >   * new callbacks or the like can be added while we unload it */
653 >  LIST_REMOVE(module, modulelist);
654 >
655 >  /* Ensure that callbacks and use_module() calls are properly undone */
656 >  LIST_FOREACH(tmp, modulelist)
657 >  {
658 >    ARRAY_FOREACH(i, tmp->users)
659 >    {
660 >      if (tmp->users[i] == module)
661 >      {
662 >        log("modules: Module `%s' forgot to unuse_module() for"
663 >            " module `%s'", module->name, tmp->name);
664 >        ARRAY_REMOVE(tmp->users, i);
665 >        i--;
666 >      }
667 >    }
668 >    ARRAY_FOREACH(i, tmp->callbacks)
669 >    {
670 >      int j;
671 >      /* Don't warn for callbacks that couldn't have been removed
672 >       * because the callback was in use (e.g. for shutting down
673 >       * after a crash) */
674 >      if (tmp->callbacks[i].calling)
675 >        continue;
676 >      ARRAY_FOREACH(j, tmp->callbacks[i].funcs)
677 >      {
678 >        if (tmp->callbacks[i].funcs[j].adder == module)
679 >        {
680 >          log("modules: Module `%s' forgot to remove callback"
681 >              " `%s' from module `%s'", module->name,
682 >              tmp->callbacks[i].name, tmp->name);
683 >          ARRAY_REMOVE(tmp->callbacks[i].funcs, j);
684 >          j--;
685          }
686 +      }
687      }
688 <    free(module->callbacks);
689 <
690 <    /* Clean up and free the module data */
691 <    call_callback_1(cb_unload_module, module);
692 <    deconfigure(module->modconfig);
693 <    free(module->name);
694 <    my_dlclose(module->dllhandle);
695 <    free(module);
688 >  }
689 >  ARRAY_FOREACH(i, module->callbacks)
690 >  {
691 >    if (module->callbacks[i].name)
692 >    {
693 >      log("modules: Module `%s' forgot to unregister callback `%s'",
694 >          module->name, module->callbacks[i].name);
695 >      free(module->callbacks[i].name);
696 >      free(module->callbacks[i].funcs);
697 >    }
698 >  }
699 >  free(module->callbacks);
700 >
701 >  /* Clean up and free the module data */
702 >  call_callback_1(cb_unload_module, module);
703 >  deconfigure(module->modconfig);
704 >  free(module->name);
705 >  my_dlclose(module->dllhandle);
706 >  free(module);
707  
708 <    return 1;
708 >  return 1;
709   }
710  
711   /*************************************************************************/
# Line 641 | Line 714 | static int internal_unload_module(Module
714   * module exists.
715   */
716  
717 < Module *find_module(const char *modulename)
717 > Module *
718 > find_module(const char *modulename)
719   {
720 <    Module *result;
720 >  Module *result;
721  
722 <    if (!modulename) {
723 <        log("find_module(): modulename is NULL!");
724 <        return NULL;
725 <    }
726 <    LIST_SEARCH(modulelist, name, modulename, strcmp, result);
727 <    return result;
722 >  if (!modulename)
723 >  {
724 >    log("find_module(): modulename is NULL!");
725 >    return NULL;
726 >  }
727 >  LIST_SEARCH(modulelist, name, modulename, strcmp, result);
728 >  return result;
729   }
730  
731   /*************************************************************************/
# Line 659 | Line 734 | Module *find_module(const char *modulena
734   * unloaded while its use count is nonzero.
735   */
736  
737 < static int use_module_loopcheck(const Module *module, const Module *check)
737 > static int
738 > use_module_loopcheck(const Module * module, const Module * check)
739   {
740 <    /* Return whether `module' is used by `check' (self-references are
741 <     * ignored). */
740 >  /* Return whether `module' is used by `check' (self-references are
741 >   * ignored). */
742  
743 <    int i;
743 >  int i;
744  
745 <    ARRAY_FOREACH (i, module->users) {
746 <        if (module->users[i] != module) {
747 <            if (module->users[i] == check
748 <             || use_module_loopcheck(module->users[i], check))
749 <                return 1;
750 <        }
745 >  ARRAY_FOREACH(i, module->users)
746 >  {
747 >    if (module->users[i] != module)
748 >    {
749 >      if (module->users[i] == check
750 >          || use_module_loopcheck(module->users[i], check))
751 >        return 1;
752      }
753 <    return 0;
753 >  }
754 >  return 0;
755   }
756  
757 < void _use_module(Module *module, const Module *caller)
757 > void
758 > _use_module(Module * module, const Module * caller)
759   {
760 <    VALIDATE_MOD(module);
761 <    VALIDATE_MOD(caller);
762 <    if (module == caller) {
763 <        log("modules: BUG: Module `%s' called use_module() for itself!",
764 <            module->name);
765 <        return;
766 <    }
767 <    if (use_module_loopcheck(caller, module)) {
768 <        log("modules: BUG: use_module loop detected (called by `%s' for `%s')",
769 <            caller->name, module->name);
770 <        return;
771 <    }
772 <    ARRAY_EXTEND(module->users);
773 <    module->users[module->users_count-1] = caller;
760 >  VALIDATE_MOD(module);
761 >  VALIDATE_MOD(caller);
762 >  if (module == caller)
763 >  {
764 >    log("modules: BUG: Module `%s' called use_module() for itself!",
765 >        module->name);
766 >    return;
767 >  }
768 >  if (use_module_loopcheck(caller, module))
769 >  {
770 >    log("modules: BUG: use_module loop detected (called by `%s' for `%s')",
771 >        caller->name, module->name);
772 >    return;
773 >  }
774 >  ARRAY_EXTEND(module->users);
775 >  module->users[module->users_count - 1] = caller;
776   }
777  
778   /*************************************************************************/
# Line 700 | Line 781 | void _use_module(Module *module, const M
781   * which case this routine does nothing.
782   */
783  
784 < void _unuse_module(Module *module, const Module *caller)
784 > void
785 > _unuse_module(Module * module, const Module * caller)
786   {
787 <    int i;
787 >  int i;
788  
789 <    if (!module)
790 <        return;
791 <    VALIDATE_MOD(module);
792 <    VALIDATE_MOD(caller);
793 <    if (module == caller) {
794 <        log("modules: BUG: Module `%s' called unuse_module() for itself!",
795 <            module->name);
796 <        return;
797 <    }
798 <    if (module->users_count == 0) {
799 <        log("modules: BUG: trying to unuse module `%s' with use count 0"
800 <            " from module `%s'", module->name, caller->name);
801 <        return;
802 <    }
803 <    ARRAY_SEARCH_PLAIN_SCALAR(module->users, caller, i);
804 <    if (i >= module->users_count) {
805 <        log("modules: BUG: trying to unuse module `%s' from module `%s' but"
806 <            " caller not found in user list!", module->name, caller->name);
807 <        return;
808 <    }
809 <    ARRAY_REMOVE(module->users, i);
789 >  if (!module)
790 >    return;
791 >  VALIDATE_MOD(module);
792 >  VALIDATE_MOD(caller);
793 >  if (module == caller)
794 >  {
795 >    log("modules: BUG: Module `%s' called unuse_module() for itself!",
796 >        module->name);
797 >    return;
798 >  }
799 >  if (module->users_count == 0)
800 >  {
801 >    log("modules: BUG: trying to unuse module `%s' with use count 0"
802 >        " from module `%s'", module->name, caller->name);
803 >    return;
804 >  }
805 >  ARRAY_SEARCH_PLAIN_SCALAR(module->users, caller, i);
806 >  if (i >= module->users_count)
807 >  {
808 >    log("modules: BUG: trying to unuse module `%s' from module `%s' but"
809 >        " caller not found in user list!", module->name, caller->name);
810 >    return;
811 >  }
812 >  ARRAY_REMOVE(module->users, i);
813   }
814  
815   /*************************************************************************/
# Line 735 | Line 820 | void _unuse_module(Module *module, const
820   * be left alone).
821   */
822  
823 < int reconfigure_modules(void)
823 > int
824 > reconfigure_modules(void)
825   {
826 <    Module *mod;
826 >  Module *mod;
827  
828 <    call_callback_1(cb_reconfigure, 0);
829 <    LIST_FOREACH (mod, modulelist) {
830 <        if (!configure(mod->name, mod->modconfig, CONFIGURE_READ))
831 <            return 0;
832 <    }
833 <    LIST_FOREACH (mod, modulelist)
834 <        configure(mod->name, mod->modconfig, CONFIGURE_SET);
835 <    call_callback_1(cb_reconfigure, 1);
836 <    return 1;
828 >  call_callback_1(cb_reconfigure, 0);
829 >  LIST_FOREACH(mod, modulelist)
830 >  {
831 >    if (!configure(mod->name, mod->modconfig, CONFIGURE_READ))
832 >      return 0;
833 >  }
834 >  LIST_FOREACH(mod, modulelist)
835 >    configure(mod->name, mod->modconfig, CONFIGURE_SET);
836 >  call_callback_1(cb_reconfigure, 1);
837 >  return 1;
838   }
839  
840   /*************************************************************************/
# Line 762 | Line 849 | int reconfigure_modules(void)
849   * no error should be printed for nonexistence, use check_module_symbol().
850   */
851  
852 < void *_get_module_symbol(Module *module, const char *symname,
853 <                         const Module *caller)
854 < {
855 <    void *value;
856 <
857 <    if (!check_module_symbol(module, symname, &value, NULL)) {
858 <        if (module) {
859 <            log("%s: Unable to resolve symbol `%s' in module `%s'",
860 <                get_module_name(caller), symname, get_module_name(module));
861 <        } else {
862 <            log("%s: Unable to resolve symbol `%s'",
863 <                get_module_name(caller), symname);
864 <        }
865 <        return NULL;
852 > void *
853 > _get_module_symbol(Module * module, const char *symname,
854 >                   const Module * caller)
855 > {
856 >  void *value;
857 >
858 >  if (!check_module_symbol(module, symname, &value, NULL))
859 >  {
860 >    if (module)
861 >    {
862 >      log("%s: Unable to resolve symbol `%s' in module `%s'",
863 >          get_module_name(caller), symname, get_module_name(module));
864 >    }
865 >    else
866 >    {
867 >      log("%s: Unable to resolve symbol `%s'",
868 >          get_module_name(caller), symname);
869      }
870 <    return value;
870 >    return NULL;
871 >  }
872 >  return value;
873   }
874  
875   /*************************************************************************/
# Line 789 | Line 881 | void *_get_module_symbol(Module *module,
881   * in the variable it points to.
882   */
883  
884 < int check_module_symbol(Module *module, const char *symname,
885 <                        void **resultptr, const char **errorptr)
886 < {
887 <    void *value;
888 <    const char *error;
889 <
890 <    (void) my_dlerror();  /* clear any previous error */
891 <    value = my_dlsym(module ? module->dllhandle : NULL, symname);
892 <    error = my_dlerror();
893 <    if (error) {
894 <        if (errorptr)
895 <            *errorptr = error;
896 <        return 0;
897 <    } else {
898 <        if (resultptr)
899 <            *resultptr = value;
900 <        return 1;
901 <    }
884 > int
885 > check_module_symbol(Module * module, const char *symname,
886 >                    void **resultptr, const char **errorptr)
887 > {
888 >  void *value;
889 >  const char *error;
890 >
891 >  (void) my_dlerror();          /* clear any previous error */
892 >  value = my_dlsym(module ? module->dllhandle : NULL, symname);
893 >  error = my_dlerror();
894 >  if (error)
895 >  {
896 >    if (errorptr)
897 >      *errorptr = error;
898 >    return 0;
899 >  }
900 >  else
901 >  {
902 >    if (resultptr)
903 >      *resultptr = value;
904 >    return 1;
905 >  }
906   }
907  
908   /*************************************************************************/
# Line 815 | Line 911 | int check_module_symbol(Module *module,
911   * string "core".
912   */
913  
914 < const char *get_module_name(const Module *module)
914 > const char *
915 > get_module_name(const Module * module)
916   {
917 <    return module ? module->name : "core";
917 >  return module ? module->name : "core";
918   }
919  
920   /*************************************************************************/
# Line 828 | Line 925 | const char *get_module_name(const Module
925   * found.
926   */
927  
928 < static CallbackInfo *find_callback(Module *module, const char *name)
928 > static CallbackInfo *
929 > find_callback(Module * module, const char *name)
930   {
931 <    int i;
931 >  int i;
932  
933 <    ARRAY_FOREACH (i, module->callbacks) {
934 <        if (module->callbacks[i].name
935 <         && strcmp(module->callbacks[i].name,name) == 0)
936 <            break;
937 <    }
938 <    if (i == module->callbacks_count)
939 <        return NULL;
940 <    return &module->callbacks[i];
933 >  ARRAY_FOREACH(i, module->callbacks)
934 >  {
935 >    if (module->callbacks[i].name
936 >        && strcmp(module->callbacks[i].name, name) == 0)
937 >      break;
938 >  }
939 >  if (i == module->callbacks_count)
940 >    return NULL;
941 >  return &module->callbacks[i];
942   }
943  
944   /*************************************************************************/
# Line 850 | Line 949 | static CallbackInfo *find_callback(Modul
949   * nonnegative integer) or -1 on error.
950   */
951  
952 < int _register_callback(Module *module, const char *name)
952 > int
953 > _register_callback(Module * module, const char *name)
954   {
955 <    int i;
955 >  int i;
956  
957 <    log_debug(2, "register_callback(%s, \"%s\")",
858 <              module ? module->name : "core", name);
859 <    VALIDATE_MOD(module, -1);
860 <    if (find_callback(module, name)) {
861 <        log("BUG: register_callback(%s,\"%s\"): callback already registered",
957 >  log_debug(2, "register_callback(%s, \"%s\")",
958              module ? module->name : "core", name);
959 <        return -1;
960 <    }
961 <    i = module->callbacks_count;
962 <    ARRAY_EXTEND(module->callbacks);
963 <    module->callbacks[i].name = sstrdup(name);
964 <    module->callbacks[i].calling = 0;
965 <    module->callbacks[i].funcs_count = 0;
966 <    module->callbacks[i].funcs = NULL;
967 <    return i;
959 >  VALIDATE_MOD(module, -1);
960 >  if (find_callback(module, name))
961 >  {
962 >    log("BUG: register_callback(%s,\"%s\"): callback already registered",
963 >        module ? module->name : "core", name);
964 >    return -1;
965 >  }
966 >  i = module->callbacks_count;
967 >  ARRAY_EXTEND(module->callbacks);
968 >  module->callbacks[i].name = sstrdup(name);
969 >  module->callbacks[i].calling = 0;
970 >  module->callbacks[i].funcs_count = 0;
971 >  module->callbacks[i].funcs = NULL;
972 >  return i;
973   }
974  
975   /*************************************************************************/
# Line 877 | Line 978 | int _register_callback(Module *module, c
978   * returned nonzero, 0 if all callbacks returned zero, or -1 on error.
979   */
980  
981 < int _call_callback_5(Module *module, int id, void *arg1, void *arg2,
982 <                     void *arg3, void *arg4, void *arg5)
983 < {
984 <    CallbackInfo *cl;
985 <    int res = 0;
986 <    int i;
987 <
988 <    VALIDATE_MOD(module, -1);
989 <    if (id < 0 || id >= module->callbacks_count)
990 <        return -1;
991 <    cl = &module->callbacks[id];
992 <    cl->calling = 1;
993 <    ARRAY_FOREACH (i, cl->funcs) {
994 <        res = cl->funcs[i].func(arg1, arg2, arg3, arg4, arg5);
995 <        if (res != 0)
996 <            break;
997 <    }
998 <    if (cl->calling == 2) {  /* flag indicating some callbacks were removed */
999 <        ARRAY_FOREACH (i, cl->funcs) {
1000 <            if (!cl->funcs[i].func) {
1001 <                ARRAY_REMOVE(cl->funcs, i);
1002 <                i--;
1003 <            }
1004 <        }
1005 <    }
1006 <    cl->calling = 0;
1007 <    return res;
981 > int
982 > _call_callback_5(Module * module, int id, void *arg1, void *arg2,
983 >                 void *arg3, void *arg4, void *arg5)
984 > {
985 >  CallbackInfo *cl;
986 >  int res = 0;
987 >  int i;
988 >
989 >  VALIDATE_MOD(module, -1);
990 >  if (id < 0 || id >= module->callbacks_count)
991 >    return -1;
992 >  cl = &module->callbacks[id];
993 >  cl->calling = 1;
994 >  ARRAY_FOREACH(i, cl->funcs)
995 >  {
996 >    res = cl->funcs[i].func(arg1, arg2, arg3, arg4, arg5);
997 >    if (res != 0)
998 >      break;
999 >  }
1000 >  if (cl->calling == 2)
1001 >  {                             /* flag indicating some callbacks were removed */
1002 >    ARRAY_FOREACH(i, cl->funcs)
1003 >    {
1004 >      if (!cl->funcs[i].func)
1005 >      {
1006 >        ARRAY_REMOVE(cl->funcs, i);
1007 >        i--;
1008 >      }
1009 >    }
1010 >  }
1011 >  cl->calling = 0;
1012 >  return res;
1013   }
1014  
1015   /*************************************************************************/
1016  
1017   /* Delete a callback. */
1018  
1019 < int _unregister_callback(Module *module, int id)
1019 > int
1020 > _unregister_callback(Module * module, int id)
1021   {
1022 <    CallbackInfo *cl;
1022 >  CallbackInfo *cl;
1023  
1024 <    VALIDATE_MOD(module, 0);
1025 <    log_debug(2, "unregister_callback(%s, %d)", module->name, id);
1026 <    if (id < 0 || id >= module->callbacks_count) {
1027 <        log("unregister_callback(): BUG: invalid callback ID %d for module"
1028 <            " `%s'", id, module->name);
1029 <        return 0;
1030 <    }
1031 <    cl = &module->callbacks[id];
1032 <    if (!cl->name) {
1033 <        log("unregister_callback(): BUG: callback ID %d for module `%s'"
1034 <            " is unused (double unregister?)", id, module->name);
1035 <        return 0;
1036 <    }
1037 <    free(cl->funcs);
1038 <    free(cl->name);
1039 <    cl->funcs = NULL;
1040 <    cl->name = NULL;
1041 <    return 1;
1024 >  VALIDATE_MOD(module, 0);
1025 >  log_debug(2, "unregister_callback(%s, %d)", module->name, id);
1026 >  if (id < 0 || id >= module->callbacks_count)
1027 >  {
1028 >    log("unregister_callback(): BUG: invalid callback ID %d for module"
1029 >        " `%s'", id, module->name);
1030 >    return 0;
1031 >  }
1032 >  cl = &module->callbacks[id];
1033 >  if (!cl->name)
1034 >  {
1035 >    log("unregister_callback(): BUG: callback ID %d for module `%s'"
1036 >        " is unused (double unregister?)", id, module->name);
1037 >    return 0;
1038 >  }
1039 >  free(cl->funcs);
1040 >  free(cl->name);
1041 >  cl->funcs = NULL;
1042 >  cl->name = NULL;
1043 >  return 1;
1044   }
1045  
1046   /*************************************************************************/
# Line 941 | Line 1050 | int _unregister_callback(Module *module,
1050   * called in the order they were added.
1051   */
1052  
1053 < int _add_callback_pri(Module *module, const char *name, callback_t callback,
1054 <                      int priority, const Module *caller)
1055 < {
1056 <    CallbackInfo *cl;
1057 <    int n;
1058 <
1059 <    log_debug(2, "add_callback_pri(%s, \"%s\", %p, %d)",
1060 <              module ? module->name : "core", name ? name : "(null)",
1061 <              callback, priority);
1062 <    VALIDATE_MOD(module, 0);
1063 <    VALIDATE_MOD(caller, 0);
1064 <    cl = find_callback(module, name);
1065 <    if (!cl) {
1066 <        log_debug(2, "-- callback not found");
1067 <        return 0;
1068 <    }
1069 <    if (priority < CBPRI_MIN || priority > CBPRI_MAX) {
1070 <        log("add_callback_pri(): priority (%d) out of range for callback"
1071 <            " `%s' in module `%s'",
1072 <            priority, name, module ? module->name : "core");
1073 <        return 0;
1074 <    }
1075 <    ARRAY_FOREACH (n, cl->funcs) {
1076 <        if (cl->funcs[n].pri < priority)
1077 <            break;
1078 <    }
1079 <    ARRAY_INSERT(cl->funcs, n);
1080 <    cl->funcs[n].func = callback;
1081 <    cl->funcs[n].adder = caller;
1082 <    cl->funcs[n].pri = priority;
1083 <    return 1;
1053 > int
1054 > _add_callback_pri(Module * module, const char *name, callback_t callback,
1055 >                  int priority, const Module * caller)
1056 > {
1057 >  CallbackInfo *cl;
1058 >  int n;
1059 >
1060 >  log_debug(2, "add_callback_pri(%s, \"%s\", %p, %d)",
1061 >            module ? module->name : "core", name ? name : "(null)",
1062 >            callback, priority);
1063 >  VALIDATE_MOD(module, 0);
1064 >  VALIDATE_MOD(caller, 0);
1065 >  cl = find_callback(module, name);
1066 >  if (!cl)
1067 >  {
1068 >    log_debug(2, "-- callback not found");
1069 >    return 0;
1070 >  }
1071 >  if (priority < CBPRI_MIN || priority > CBPRI_MAX)
1072 >  {
1073 >    log("add_callback_pri(): priority (%d) out of range for callback"
1074 >        " `%s' in module `%s'",
1075 >        priority, name, module ? module->name : "core");
1076 >    return 0;
1077 >  }
1078 >  ARRAY_FOREACH(n, cl->funcs)
1079 >  {
1080 >    if (cl->funcs[n].pri < priority)
1081 >      break;
1082 >  }
1083 >  ARRAY_INSERT(cl->funcs, n);
1084 >  cl->funcs[n].func = callback;
1085 >  cl->funcs[n].adder = caller;
1086 >  cl->funcs[n].pri = priority;
1087 >  return 1;
1088   }
1089  
1090   /*************************************************************************/
1091  
1092   /* Remove (unhook) a function from a callback. */
1093 < int _remove_callback(Module *module, const char *name, callback_t callback,
1094 <                     const Module *caller)
1095 < {
1096 <    CallbackInfo *cl;
1097 <    int index;
1098 <
1099 <    log_debug(2, "remove_callback(%s, \"%s\", %p)",
1100 <              module ? module->name : "core", name, callback);
1101 <    VALIDATE_MOD(module, 0);
1102 <    VALIDATE_MOD(caller, 0);
1103 <    cl = find_callback(module, name);
1104 <    if (!cl)
1105 <        return 0;
1106 <    ARRAY_SEARCH_SCALAR(cl->funcs, func, callback, index);
1107 <    if (index == cl->funcs_count)
1108 <        return 0;
1109 <    if (cl->funcs[index].adder != caller) {
1110 <        log("remove_callback(%s, \"%s\"): BUG: caller `%s' tried to remove"
1111 <            " callback %p added by different module `%s'!",
1112 <            get_module_name(module), name, get_module_name(caller), callback,
1113 <            get_module_name(cl->funcs[index].adder));
1114 <        return 0;
1115 <    }
1116 <    if (cl->calling) {
1117 <        cl->funcs[index].func = NULL;
1118 <        cl->calling = 2;  /* flag to call_callback() indicating CB removed */
1119 <    } else {
1120 <        ARRAY_REMOVE(cl->funcs, index);
1121 <    }
1122 <    return 1;
1093 > int
1094 > _remove_callback(Module * module, const char *name, callback_t callback,
1095 >                 const Module * caller)
1096 > {
1097 >  CallbackInfo *cl;
1098 >  int index;
1099 >
1100 >  log_debug(2, "remove_callback(%s, \"%s\", %p)",
1101 >            module ? module->name : "core", name, callback);
1102 >  VALIDATE_MOD(module, 0);
1103 >  VALIDATE_MOD(caller, 0);
1104 >  cl = find_callback(module, name);
1105 >  if (!cl)
1106 >    return 0;
1107 >  ARRAY_SEARCH_SCALAR(cl->funcs, func, callback, index);
1108 >  if (index == cl->funcs_count)
1109 >    return 0;
1110 >  if (cl->funcs[index].adder != caller)
1111 >  {
1112 >    log("remove_callback(%s, \"%s\"): BUG: caller `%s' tried to remove"
1113 >        " callback %p added by different module `%s'!",
1114 >        get_module_name(module), name, get_module_name(caller), callback,
1115 >        get_module_name(cl->funcs[index].adder));
1116 >    return 0;
1117 >  }
1118 >  if (cl->calling)
1119 >  {
1120 >    cl->funcs[index].func = NULL;
1121 >    cl->calling = 2;            /* flag to call_callback() indicating CB removed */
1122 >  }
1123 >  else
1124 >  {
1125 >    ARRAY_REMOVE(cl->funcs, index);
1126 >  }
1127 >  return 1;
1128   }
1129  
1130   /*************************************************************************/

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)