#include <eggdrop/eggdrop.h>
#include <ltdl.h>
#include <unistd.h>
Go to the source code of this file.
Data Structures | |
struct | module_list |
Defines | |
#define | find_active_module(name) find_module((name), module_list_head) |
#define | find_deleted_module(name) find_module((name), deleted_head) |
Typedefs | |
typedef struct module_list | module_list_t |
Functions | |
static int | module_cleanup (void *ignored) |
Calls module_really_unload() for every module marked for unloading. | |
static module_list_t * | find_module (const char *name, module_list_t *head) |
int | module_init (void) |
int | module_shutdown (void) |
Shuts down the module interface. | |
int | module_add_dir (const char *moddir) |
int | module_load (const char *name) |
Load a module. | |
int | module_unload (const char *name, int why) |
Unload a module. | |
static void | module_really_unload (module_list_t *entry) |
Remove a module from the process's memory. | |
egg_module_t * | module_lookup (const char *name) |
int | module_loaded (const char *name) |
void * | module_get_api (const char *name, int major, int minor) |
int | module_addref (const char *name) |
int | module_decref (const char *name) |
int | module_list (const char ***names) |
Variables | |
static const char | rcsid [] = "$Id: module.c,v 1.15 2007-09-13 22:20:55 sven Exp $" |
static module_list_t * | module_list_head = NULL |
static module_list_t * | deleted_head = NULL |
static bind_table_t * | BT_load |
static bind_table_t * | BT_unload |
#define find_active_module | ( | name | ) | find_module((name), module_list_head) |
Definition at line 41 of file module.c.
Referenced by module_addref(), module_decref(), module_get_api(), module_load(), module_loaded(), module_lookup(), and module_unload().
#define find_deleted_module | ( | name | ) | find_module((name), deleted_head) |
typedef struct module_list module_list_t |
static module_list_t* find_module | ( | const char * | name, | |
module_list_t * | head | |||
) | [static] |
Definition at line 44 of file module.c.
References module_list::modinfo, egg_module::name, module_list::next, and NULL.
00045 { 00046 module_list_t *entry; 00047 00048 for (entry = head; entry; entry = entry->next) { 00049 if (!strcasecmp(name, entry->modinfo.name)) return(entry); 00050 } 00051 return(NULL); 00052 }
int module_add_dir | ( | const char * | moddir | ) |
Definition at line 95 of file module.c.
References egg_mprintf().
Referenced by core_init().
00096 { 00097 char *fixed_moddir; 00098 00099 if (*moddir != '/') { 00100 char cwd[1024]; 00101 00102 cwd[0] = 0; 00103 getcwd(cwd, sizeof(cwd)); 00104 cwd[sizeof(cwd)-1] = 0; 00105 fixed_moddir = egg_mprintf("%s/%s", cwd, moddir); 00106 } 00107 else fixed_moddir = (char *)moddir; 00108 00109 lt_dladdsearchdir(fixed_moddir); 00110 if (fixed_moddir != moddir) free(fixed_moddir); 00111 return(0); 00112 }
int module_addref | ( | const char * | name | ) |
Definition at line 320 of file module.c.
References find_active_module, and module_list::refcount.
00321 { 00322 module_list_t *entry; 00323 00324 entry = find_active_module(name); 00325 if (!entry) return(-1); 00326 entry->refcount++; 00327 return(0); 00328 }
static int module_cleanup | ( | void * | ignored | ) | [static] |
Calls module_really_unload() for every module marked for unloading.
This function is called automatically by garbage_run() if a module has has been closed.
Definition at line 287 of file module.c.
References deleted_head, and module_really_unload().
Referenced by module_unload().
00288 { 00289 while (deleted_head) module_really_unload(deleted_head); 00290 00291 return 0; 00292 }
int module_decref | ( | const char * | name | ) |
Definition at line 330 of file module.c.
References find_active_module, and module_list::refcount.
00331 { 00332 module_list_t *entry; 00333 00334 entry = find_active_module(name); 00335 if (!entry) return(-1); 00336 entry->refcount--; 00337 return(0); 00338 }
void* module_get_api | ( | const char * | name, | |
int | major, | |||
int | minor | |||
) |
Definition at line 310 of file module.c.
References find_active_module, module_list::modinfo, egg_module::module_api, NULL, and module_list::refcount.
Referenced by chanserv_init().
00311 { 00312 module_list_t *entry; 00313 00314 entry = find_active_module(name); 00315 if (!entry) return(NULL); 00316 entry->refcount++; 00317 return entry->modinfo.module_api; 00318 }
int module_init | ( | void | ) |
Definition at line 54 of file module.c.
References bind_table_add(), BTN_LOAD_MODULE, BTN_UNLOAD_MODULE, and MATCH_MASK.
Referenced by eggdrop_init().
00055 { 00056 BT_load = bind_table_add(BTN_LOAD_MODULE, 1, "s", MATCH_MASK, 0); /* DDD */ 00057 BT_unload = bind_table_add(BTN_UNLOAD_MODULE, 2, "ss", MATCH_MASK, 0); /* DDD */ 00058 return(0); 00059 }
int module_list | ( | const char *** | names | ) |
Definition at line 340 of file module.c.
References module_list::modinfo, egg_module::name, module_list::next, and NULL.
Referenced by party_modules().
00341 { 00342 module_list_t *entry; 00343 int i = 0; 00344 00345 for (entry = module_list_head; entry; entry = entry->next) i++; 00346 *names = malloc((i + 1) * sizeof(char **)); 00347 i = 0; 00348 for (entry = module_list_head; entry; entry = entry->next) { 00349 (*names)[i] = entry->modinfo.name; 00350 i++; 00351 } 00352 (*names)[i] = NULL; 00353 return(i); 00354 }
int module_load | ( | const char * | name | ) |
Load a module.
This function loads a module and executes its start function. If the module name does not contain a path the default paths will be searched. If it does have an extenteion the plattforms default library extentions will be added.
name | The name of the module to load. |
-1 if the module is already loaded. (Nothing will be logged.)
-2 if the module could not be opened. (This will be logged.)
-3 if no start function is present. (Nothing will be logged.)
-4 if the start function returned an error. (Nothing will be logged.)
-5 if the module can't be loaded because it's marked for unloading. (Nothing will be logged.)
Definition at line 131 of file module.c.
References bind_check(), egg_mprintf(), find_active_module, find_deleted_module, module_list::hand, LOG_MISC, module_list::modinfo, module_list::next, NULL, module_list::prev, putlog(), and module_list::refcount.
Referenced by core_init(), and party_loadmod().
00132 { 00133 lt_dlhandle hand; 00134 module_list_t *entry; 00135 egg_start_func_t startfunc; 00136 char *startname; 00137 00138 00139 /* See if it's already loaded. */ 00140 entry = find_active_module(name); 00141 if (entry) return(-1); 00142 entry = find_deleted_module(name); 00143 if (entry) return(-5); 00144 00145 hand = lt_dlopenext(name); 00146 if (!hand) { 00147 const char *err = lt_dlerror(); 00148 putlog(LOG_MISC, "*", "Error loading module %s: %s", name, err); 00149 return(-2); 00150 } 00151 00152 startname = egg_mprintf("%s_LTX_start", name); 00153 startfunc = (egg_start_func_t)lt_dlsym(hand, startname); 00154 free(startname); 00155 if (!startfunc) { 00156 startfunc = (egg_start_func_t)lt_dlsym(hand, "start"); 00157 if (!startfunc) { 00158 lt_dlclose(hand); 00159 return(-3); 00160 } 00161 } 00162 00163 /* Create an entry for it. */ 00164 entry = calloc(1, sizeof(*entry)); 00165 entry->prev = NULL; 00166 entry->next = module_list_head; 00167 entry->refcount = 0; 00168 entry->hand = hand; 00169 module_list_head = entry; 00170 00171 if (startfunc(&entry->modinfo)) { 00172 module_list_head = module_list_head->next; 00173 free(entry); 00174 return(-4); 00175 } 00176 00177 putlog(LOG_MISC, "*", "Module loaded: %s", name); 00178 bind_check(BT_load, NULL, name, name); 00179 00180 return(0); 00181 }
int module_loaded | ( | const char * | name | ) |
Definition at line 303 of file module.c.
References find_active_module, and NULL.
00304 { 00305 if (name == NULL) return 0; 00306 00307 return (find_active_module(name) != NULL); 00308 }
egg_module_t* module_lookup | ( | const char * | name | ) |
Definition at line 294 of file module.c.
References find_active_module, module_list::modinfo, and NULL.
00295 { 00296 module_list_t *entry; 00297 00298 entry = find_active_module(name); 00299 if (entry) return(&entry->modinfo); 00300 return(NULL); 00301 }
static void module_really_unload | ( | module_list_t * | entry | ) | [static] |
Remove a module from the process's memory.
Tis function will call the modules's unload function, remove all asyncronous events owned by this module and finally remove the module itself from memory.
entry | The module to remove. This must be in the list of deleted modules. |
Definition at line 247 of file module.c.
References deleted_head, egg_module::event_cleanup, module_list::hand, LOG_MISC, module_list::modinfo, egg_module::name, module_list::next, module_list::prev, putlog(), script_remove_events_by_owner(), and egg_module::unload_func.
Referenced by module_cleanup().
00248 { 00249 int errors; 00250 const char *error; 00251 module_list_t *m; 00252 00253 if (entry->prev) entry->prev->next = entry->next; 00254 else deleted_head = entry->next; 00255 if (entry->next) entry->next->prev = entry->prev; 00256 00257 if (entry->modinfo.unload_func) entry->modinfo.unload_func(); 00258 00259 script_remove_events_by_owner(&entry->modinfo, 0); 00260 00261 for (m = module_list_head; m; m = m->next) { 00262 if (m->modinfo.event_cleanup) m->modinfo.event_cleanup(&entry->modinfo); 00263 } 00264 00265 for (m = deleted_head; m; m = m->next) { 00266 if (m->modinfo.event_cleanup) m->modinfo.event_cleanup(&entry->modinfo); 00267 } 00268 00269 errors = lt_dlclose(entry->hand); 00270 if (errors) { 00271 putlog(LOG_MISC, "*", "Error unloading %s!", entry->modinfo.name); 00272 while ((error = lt_dlerror())) putlog(LOG_MISC, "*", "ltdlerror: %s", error); 00273 } 00274 00275 free(entry); 00276 }
int module_shutdown | ( | void | ) |
Shuts down the module interface.
This function unloads all loaded modules and deletes the load and unload bind tables.
The module_unload() function is called for every module that is currently loaded. If there is still a module loaded, for example because of dependencies, module_unload() is called again. This is done until either all modules have been unloaded or no more modules could be unloaded.
Definition at line 75 of file module.c.
References bind_table_del(), garbage_run(), module_list::modinfo, MODULE_RESTART, module_unload(), egg_module::name, and module_list::next.
Referenced by eggdrop_shutdown().
00076 { 00077 int unloaded; 00078 module_list_t *entry, *next; 00079 00080 do { 00081 unloaded = 0; 00082 for (entry = module_list_head; entry; entry = next) { 00083 next = entry->next; 00084 if (!module_unload(entry->modinfo.name, MODULE_RESTART)) unloaded = 1; 00085 } 00086 } while (unloaded); 00087 00088 bind_table_del(BT_load); 00089 bind_table_del(BT_unload); 00090 00091 garbage_run(); 00092 return (0); 00093 }
int module_unload | ( | const char * | name, | |
int | why | |||
) |
Unload a module.
If a module's reference count is 0 its closing function will be executed. If the closing function did not veto the unloading it will be removed from the list of active modules, the "unload" bind is triggered and a cleanup run is sceduled.
name | The name of the module to unload. | |
why | The reason this function was called: MODULE_USER, MODULE_RESTART or MODULE_SHUTDOWN. |
-1 if the module is not loaded. (Nothing will be logged.)
-2 if the module is in use by another module. (Nothing will be logged.)
-3 if the module's closing function vetoed. (Nothing will be logged.)
Definition at line 201 of file module.c.
References bind_check(), egg_module::close_func, deleted_head, find_active_module, garbage_add(), GARBAGE_ONCE, LOG_MISC, module_list::modinfo, module_cleanup(), MODULE_SHUTDOWN, MODULE_USER, module_list::next, NULL, module_list::prev, putlog(), and module_list::refcount.
Referenced by module_shutdown(), party_unloadmod(), and script_module_unload().
00202 { 00203 module_list_t *entry; 00204 int retval; 00205 00206 entry = find_active_module(name); 00207 if (!entry) return(-1); 00208 if (entry->refcount > 0) return(-2); 00209 if (entry->modinfo.close_func) { 00210 retval = entry->modinfo.close_func(why); 00211 if (retval) return(-3); 00212 } 00213 00214 if (entry->prev) entry->prev->next = entry->next; 00215 else module_list_head = entry->next; 00216 if (entry->next) entry->next->prev = entry->prev; 00217 00218 entry->next = NULL; 00219 if (!deleted_head) { 00220 deleted_head = entry; 00221 entry->prev = NULL; 00222 } else { 00223 module_list_t *tail; 00224 00225 for (tail = deleted_head; tail->next; tail = tail->next); 00226 tail->next = entry; 00227 entry->prev = tail; 00228 } 00229 00230 bind_check(BT_unload, NULL, name, name, why == MODULE_USER ? "request" : why == MODULE_SHUTDOWN ? "shutdown" : "restart"); 00231 putlog(LOG_MISC, "*", "Module unloaded: %s", name); 00232 garbage_add(module_cleanup, NULL, GARBAGE_ONCE); 00233 return 0; 00234 }
bind_table_t* BT_load [static] |
bind_table_t * BT_unload [static] |
module_list_t * deleted_head = NULL [static] |
Definition at line 36 of file module.c.
Referenced by module_cleanup(), module_really_unload(), and module_unload().
module_list_t* module_list_head = NULL [static] |
const char rcsid[] = "$Id: module.c,v 1.15 2007-09-13 22:20:55 sven Exp $" [static] |