#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <dirent.h>
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cdr.h"
#include "asterisk/enum.h"
#include "asterisk/rtp.h"
#include "asterisk/http.h"
#include "asterisk/lock.h"
#include "asterisk/features.h"
#include <dlfcn.h>
#include "asterisk/md5.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | ast_module |
struct | ast_module_user |
struct | load_order |
struct | load_order_entry |
struct | loadupdate |
struct | module_list |
struct | module_user_list |
struct | reload_classes |
struct | reload_queue |
struct | reload_queue_item |
struct | updaters |
Defines | |
#define | RTLD_LOCAL 0 |
#define | RTLD_NOW 0 |
Functions | |
ast_module_user * | __ast_module_user_add (struct ast_module *mod, struct ast_channel *chan) |
void | __ast_module_user_hangup_all (struct ast_module *mod) |
void | __ast_module_user_remove (struct ast_module *mod, struct ast_module_user *u) |
static struct load_order_entry * | add_to_load_order (const char *resource, struct load_order *load_order) |
int | ast_load_resource (const char *resource_name) |
Load a module. | |
int | ast_loader_register (int(*v)(void)) |
Add a procedure to be run when modules have been updated. | |
int | ast_loader_unregister (int(*v)(void)) |
Remove a procedure to be run when modules are updated. | |
int | ast_module_check (const char *name) |
Check if module with the name given is loaded. | |
char * | ast_module_helper (const char *line, const char *word, int pos, int state, int rpos, int needsreload) |
Match modules names for the Asterisk cli. | |
ast_module * | ast_module_ref (struct ast_module *mod) |
void | ast_module_register (const struct ast_module_info *info) |
int | ast_module_reload (const char *name) |
Reload asterisk modules. | |
void | ast_module_shutdown (void) |
Run the unload() callback for all loaded modules. | |
void | ast_module_unref (struct ast_module *mod) |
void | ast_module_unregister (const struct ast_module_info *info) |
void | ast_process_pending_reloads (void) |
Process reload requests received during startup. | |
int | ast_unload_resource (const char *resource_name, enum ast_module_unload_mode force) |
Unload a module. | |
int | ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *like), const char *like) |
Ask for a list of modules, descriptions, and use counts. | |
void | ast_update_use_count (void) |
Notify when usecount has been changed. | |
static struct ast_module * | find_resource (const char *resource, int do_lock) |
static unsigned int | inspect_module (const struct ast_module *mod) |
static int | key_matches (const unsigned char *key1, const unsigned char *key2) |
static struct ast_module * | load_dynamic_module (const char *resource_in, unsigned int global_symbols_only) |
int | load_modules (unsigned int preload_only) |
static enum ast_module_load_result | load_resource (const char *resource_name, unsigned int global_symbols_only) |
static int | printdigest (const unsigned char *d) |
static void | queue_reload_request (const char *module) |
static int | resource_name_match (const char *name1_in, const char *name2_in) |
static void | unload_dynamic_module (struct ast_module *mod) |
static int | verify_key (const unsigned char *key) |
Variables | |
static char | buildopt_sum [33] = AST_BUILDOPT_SUM |
static int | do_full_reload = 0 |
static struct module_list | embedded_module_list |
static unsigned int | embedding = 1 |
static unsigned char | expected_key [] |
static ast_mutex_t | reloadlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
ast_module * | resource_being_loaded |
Kevin P. Fleming <kpfleming@digium.com>
Luigi Rizzo <rizzo@icir.org>
Definition in file loader.c.
#define RTLD_LOCAL 0 |
#define RTLD_NOW 0 |
struct ast_module_user* __ast_module_user_add | ( | struct ast_module * | mod, | |
struct ast_channel * | chan | |||
) |
Definition at line 192 of file loader.c.
References ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::chan, ast_module_user::entry, ast_module::usecount, and ast_module::users.
Referenced by ast_func_read(), ast_func_write(), and pbx_exec().
00194 { 00195 struct ast_module_user *u = ast_calloc(1, sizeof(*u)); 00196 00197 if (!u) 00198 return NULL; 00199 00200 u->chan = chan; 00201 00202 AST_LIST_LOCK(&mod->users); 00203 AST_LIST_INSERT_HEAD(&mod->users, u, entry); 00204 AST_LIST_UNLOCK(&mod->users); 00205 00206 ast_atomic_fetchadd_int(&mod->usecount, +1); 00207 00208 ast_update_use_count(); 00209 00210 return u; 00211 }
void __ast_module_user_hangup_all | ( | struct ast_module * | mod | ) |
Definition at line 224 of file loader.c.
References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_update_use_count(), ast_module_user::chan, ast_module_user::entry, ast_module::usecount, and ast_module::users.
Referenced by ast_unload_resource().
00225 { 00226 struct ast_module_user *u; 00227 00228 AST_LIST_LOCK(&mod->users); 00229 while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) { 00230 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD); 00231 ast_atomic_fetchadd_int(&mod->usecount, -1); 00232 ast_free(u); 00233 } 00234 AST_LIST_UNLOCK(&mod->users); 00235 00236 ast_update_use_count(); 00237 }
void __ast_module_user_remove | ( | struct ast_module * | mod, | |
struct ast_module_user * | u | |||
) |
Definition at line 213 of file loader.c.
References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::entry, ast_module::usecount, and ast_module::users.
Referenced by ast_func_read(), ast_func_write(), and pbx_exec().
00214 { 00215 AST_LIST_LOCK(&mod->users); 00216 AST_LIST_REMOVE(&mod->users, u, entry); 00217 AST_LIST_UNLOCK(&mod->users); 00218 ast_atomic_fetchadd_int(&mod->usecount, -1); 00219 ast_free(u); 00220 00221 ast_update_use_count(); 00222 }
static struct load_order_entry* add_to_load_order | ( | const char * | resource, | |
struct load_order * | load_order | |||
) | [static] |
Definition at line 804 of file loader.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, ast_module_user::entry, load_order_entry::resource, and resource_name_match().
Referenced by load_modules().
00805 { 00806 struct load_order_entry *order; 00807 00808 AST_LIST_TRAVERSE(load_order, order, entry) { 00809 if (!resource_name_match(order->resource, resource)) 00810 return NULL; 00811 } 00812 00813 if (!(order = ast_calloc(1, sizeof(*order)))) 00814 return NULL; 00815 00816 order->resource = ast_strdup(resource); 00817 AST_LIST_INSERT_TAIL(load_order, order, entry); 00818 00819 return order; 00820 }
int ast_load_resource | ( | const char * | resource_name | ) |
Load a module.
resource_name | The name of the module to load. |
Definition at line 787 of file loader.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().
Referenced by file_ok_sel(), handle_load(), manager_moduleload(), and reload().
00788 { 00789 int res; 00790 AST_LIST_LOCK(&module_list); 00791 res = load_resource(resource_name, 0); 00792 AST_LIST_UNLOCK(&module_list); 00793 00794 return res; 00795 }
int ast_loader_register | ( | int(*)(void) | updater | ) |
Add a procedure to be run when modules have been updated.
updater | The function to run when modules have been updated. |
0 | on success | |
-1 | on failure. |
Definition at line 1041 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, and ast_malloc.
Referenced by show_console().
01042 { 01043 struct loadupdate *tmp; 01044 01045 if (!(tmp = ast_malloc(sizeof(*tmp)))) 01046 return -1; 01047 01048 tmp->updater = v; 01049 AST_LIST_LOCK(&updaters); 01050 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 01051 AST_LIST_UNLOCK(&updaters); 01052 01053 return 0; 01054 }
int ast_loader_unregister | ( | int(*)(void) | updater | ) |
Remove a procedure to be run when modules are updated.
updater | The updater function to unregister. |
0 | on success | |
-1 | on failure. |
Definition at line 1056 of file loader.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, and loadupdate::updater.
Referenced by exit_now().
01057 { 01058 struct loadupdate *cur; 01059 01060 AST_LIST_LOCK(&updaters); 01061 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 01062 if (cur->updater == v) { 01063 AST_LIST_REMOVE_CURRENT(entry); 01064 break; 01065 } 01066 } 01067 AST_LIST_TRAVERSE_SAFE_END; 01068 AST_LIST_UNLOCK(&updaters); 01069 01070 return cur ? 0 : -1; 01071 }
int ast_module_check | ( | const char * | name | ) |
Check if module with the name given is loaded.
name | Module name, like "chan_sip.so" |
1 | if true | |
0 | if false |
Definition at line 1028 of file loader.c.
References ast_strlen_zero(), and find_resource().
Referenced by ifmodule_read(), and manager_modulecheck().
01029 { 01030 struct ast_module *cur; 01031 01032 if (ast_strlen_zero(name)) 01033 return 0; /* FALSE */ 01034 01035 cur = find_resource(name, 1); 01036 01037 return (cur != NULL); 01038 }
char* ast_module_helper | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state, | |||
int | rpos, | |||
int | needsreload | |||
) |
Match modules names for the Asterisk cli.
line | Unused by this function, but this should be the line we are matching. | |
word | The partial name to match. | |
pos | The position the word we are completing is in. | |
state | The possible match to return. | |
rpos | The position we should be matching. This should be the same as pos. | |
needsreload | This should be 1 if we need to reload this module and 0 otherwise. This function will only return modules that are reloadble if this is 1. |
A | possible completion of the partial match. | |
NULL | if no matches were found. |
Definition at line 523 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_module_user::entry, ast_module::info, name, ast_module_info::reload, and ast_module::resource.
Referenced by handle_modlist(), handle_reload(), handle_unload(), and load_module().
00524 { 00525 struct ast_module *cur; 00526 int i, which=0, l = strlen(word); 00527 char *ret = NULL; 00528 00529 if (pos != rpos) 00530 return NULL; 00531 00532 AST_LIST_LOCK(&module_list); 00533 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00534 if (!strncasecmp(word, cur->resource, l) && 00535 (cur->info->reload || !needsreload) && 00536 ++which > state) { 00537 ret = ast_strdup(cur->resource); 00538 break; 00539 } 00540 } 00541 AST_LIST_UNLOCK(&module_list); 00542 00543 if (!ret) { 00544 for (i=0; !ret && reload_classes[i].name; i++) { 00545 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00546 ret = ast_strdup(reload_classes[i].name); 00547 } 00548 } 00549 00550 return ret; 00551 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 1073 of file loader.c.
References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.
Referenced by __oh323_new(), agi_handle_command(), alsa_new(), ast_agi_register(), ast_iax2_new(), dahdi_new(), fn_wrapper(), gtalk_new(), handle_cli_file_convert(), handle_orig(), mgcp_new(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_new(), skinny_new(), and usbradio_new().
01074 { 01075 ast_atomic_fetchadd_int(&mod->usecount, +1); 01076 ast_update_use_count(); 01077 01078 return mod; 01079 }
void ast_module_register | ( | const struct ast_module_info * | info | ) |
Definition at line 130 of file loader.c.
References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedding, ast_module_user::entry, ast_module::info, resource_being_loaded, and ast_module::users.
00131 { 00132 struct ast_module *mod; 00133 00134 if (embedding) { 00135 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1))) 00136 return; 00137 strcpy(mod->resource, info->name); 00138 } else { 00139 mod = resource_being_loaded; 00140 } 00141 00142 mod->info = info; 00143 AST_LIST_HEAD_INIT(&mod->users); 00144 00145 /* during startup, before the loader has been initialized, 00146 there are no threads, so there is no need to take the lock 00147 on this list to manipulate it. it is also possible that it 00148 might be unsafe to use the list lock at that point... so 00149 let's avoid it altogether 00150 */ 00151 if (embedding) { 00152 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry); 00153 } else { 00154 AST_LIST_LOCK(&module_list); 00155 /* it is paramount that the new entry be placed at the tail of 00156 the list, otherwise the code that uses dlopen() to load 00157 dynamic modules won't be able to find out if the module it 00158 just opened was registered or failed to load 00159 */ 00160 AST_LIST_INSERT_TAIL(&module_list, mod, entry); 00161 AST_LIST_UNLOCK(&module_list); 00162 } 00163 00164 /* give the module a copy of its own handle, for later use in registrations and the like */ 00165 *((struct ast_module **) &(info->self)) = mod; 00166 }
int ast_module_reload | ( | const char * | name | ) |
Reload asterisk modules.
name | the name of the module to reload |
1 | if the module was found but cannot be reloaded. | |
-1 | if a reload operation is already in progress. | |
2 | if the specfied module was found and reloaded. |
Definition at line 618 of file loader.c.
References ast_fully_booted, ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_tvnow(), ast_verb, ast_verbose(), ast_module::declined, ast_module_info::description, ast_module_user::entry, ast_module::flags, ast_module::info, LOG_NOTICE, queue_reload_request(), ast_module_info::reload, ast_module::resource, resource_name_match(), and ast_module::running.
Referenced by action_reload(), action_updateconfig(), ast_process_pending_reloads(), handle_reload(), manager_moduleload(), and monitor_sig_flags().
00619 { 00620 struct ast_module *cur; 00621 int res = 0; /* return value. 0 = not found, others, see below */ 00622 int i; 00623 00624 /* If we aren't fully booted, we just pretend we reloaded but we queue this 00625 up to run once we are booted up. */ 00626 if (!ast_fully_booted) { 00627 queue_reload_request(name); 00628 return 0; 00629 } 00630 00631 if (ast_mutex_trylock(&reloadlock)) { 00632 ast_verbose("The previous reload command didn't finish yet\n"); 00633 return -1; /* reload already in progress */ 00634 } 00635 ast_lastreloadtime = ast_tvnow(); 00636 00637 /* Call "predefined" reload here first */ 00638 for (i = 0; reload_classes[i].name; i++) { 00639 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00640 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00641 res = 2; /* found and reloaded */ 00642 } 00643 } 00644 00645 if (name && res) { 00646 ast_mutex_unlock(&reloadlock); 00647 return res; 00648 } 00649 00650 AST_LIST_LOCK(&module_list); 00651 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00652 const struct ast_module_info *info = cur->info; 00653 00654 if (name && resource_name_match(name, cur->resource)) 00655 continue; 00656 00657 if (!cur->flags.running || cur->flags.declined) { 00658 if (!name) 00659 continue; 00660 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00661 "Before reloading the module, you must run \"module load %s\" " 00662 "and fix whatever is preventing the module from being initialized.\n", 00663 name, name); 00664 res = 2; /* Don't report that the module was not found */ 00665 break; 00666 } 00667 00668 if (!info->reload) { /* cannot be reloaded */ 00669 if (res < 1) /* store result if possible */ 00670 res = 1; /* 1 = no reload() method */ 00671 continue; 00672 } 00673 00674 res = 2; 00675 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description); 00676 info->reload(); 00677 } 00678 AST_LIST_UNLOCK(&module_list); 00679 00680 ast_mutex_unlock(&reloadlock); 00681 00682 return res; 00683 }
void ast_module_shutdown | ( | void | ) |
Run the unload() callback for all loaded modules.
This function should be called when Asterisk is shutting down gracefully.
Definition at line 438 of file loader.c.
References AST_LIST_HEAD_DESTROY, AST_LIST_HEAD_NOLOCK_STATIC, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_module_user::entry, free, ast_module::info, ast_module_info::unload, and ast_module::users.
Referenced by quit_handler().
00439 { 00440 struct ast_module *mod; 00441 AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module); 00442 00443 /* We have to call the unload() callbacks in reverse order that the modules 00444 * exist in the module list so it is the reverse order of how they were 00445 * loaded. */ 00446 00447 AST_LIST_LOCK(&module_list); 00448 while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry))) 00449 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry); 00450 AST_LIST_UNLOCK(&module_list); 00451 00452 while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) { 00453 if (mod->info->unload) 00454 mod->info->unload(); 00455 /* Since this should only be called when shutting down "gracefully", 00456 * all channels should be down before we get to this point, meaning 00457 * there will be no module users left. */ 00458 AST_LIST_HEAD_DESTROY(&mod->users); 00459 free(mod); 00460 } 00461 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 1081 of file loader.c.
References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.
Referenced by agi_handle_command(), alsa_hangup(), ast_agi_unregister(), ast_smdi_interface_destroy(), dahdi_destroy_channel_bynum(), dahdi_hangup(), destroy(), filestream_destructor(), gtalk_hangup(), handle_cli_file_convert(), handle_orig(), iax2_predestroy(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_hangup(), and usbradio_hangup().
01082 { 01083 ast_atomic_fetchadd_int(&mod->usecount, -1); 01084 ast_update_use_count(); 01085 }
void ast_module_unregister | ( | const struct ast_module_info * | info | ) |
Definition at line 168 of file loader.c.
References ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module_user::entry, ast_module::info, and ast_module::users.
00169 { 00170 struct ast_module *mod = NULL; 00171 00172 /* it is assumed that the users list in the module structure 00173 will already be empty, or we cannot have gotten to this 00174 point 00175 */ 00176 AST_LIST_LOCK(&module_list); 00177 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00178 if (mod->info == info) { 00179 AST_LIST_REMOVE_CURRENT(entry); 00180 break; 00181 } 00182 } 00183 AST_LIST_TRAVERSE_SAFE_END; 00184 AST_LIST_UNLOCK(&module_list); 00185 00186 if (mod) { 00187 AST_LIST_HEAD_DESTROY(&mod->users); 00188 ast_free(mod); 00189 } 00190 }
void ast_process_pending_reloads | ( | void | ) |
Process reload requests received during startup.
This function requests that the loader execute the pending reload requests that were queued during server startup.
Definition at line 553 of file loader.c.
References ast_free, ast_fully_booted, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_module_reload(), do_full_reload, ast_module_user::entry, LOG_NOTICE, and reload_queue_item::module.
Referenced by main().
00554 { 00555 struct reload_queue_item *item; 00556 00557 if (!ast_fully_booted) { 00558 return; 00559 } 00560 00561 AST_LIST_LOCK(&reload_queue); 00562 00563 if (do_full_reload) { 00564 do_full_reload = 0; 00565 AST_LIST_UNLOCK(&reload_queue); 00566 ast_log(LOG_NOTICE, "Executing deferred reload request.\n"); 00567 ast_module_reload(NULL); 00568 return; 00569 } 00570 00571 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00572 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module); 00573 ast_module_reload(item->module); 00574 ast_free(item); 00575 } 00576 00577 AST_LIST_UNLOCK(&reload_queue); 00578 }
int ast_unload_resource | ( | const char * | resource_name, | |
enum | ast_module_unload_mode | |||
) |
Unload a module.
resource_name | The name of the module to unload. | |
ast_module_unload_mode | The force flag. This should be set using one of the AST_FORCE flags. |
0 | on success. | |
-1 | on error. |
Definition at line 463 of file loader.c.
References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_update_use_count(), ast_module::declined, find_resource(), ast_module::flags, ast_module::info, ast_module::lib, LOG_WARNING, ast_module_info::restore_globals, ast_module::running, unload_dynamic_module(), and ast_module::usecount.
Referenced by exit_now(), handle_unload(), manager_moduleload(), reload(), and remove_module().
00464 { 00465 struct ast_module *mod; 00466 int res = -1; 00467 int error = 0; 00468 00469 AST_LIST_LOCK(&module_list); 00470 00471 if (!(mod = find_resource(resource_name, 0))) { 00472 AST_LIST_UNLOCK(&module_list); 00473 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name); 00474 return 0; 00475 } 00476 00477 if (!(mod->flags.running || mod->flags.declined)) 00478 error = 1; 00479 00480 if (!error && (mod->usecount > 0)) { 00481 if (force) 00482 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00483 resource_name, mod->usecount); 00484 else { 00485 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00486 mod->usecount); 00487 error = 1; 00488 } 00489 } 00490 00491 if (!error) { 00492 __ast_module_user_hangup_all(mod); 00493 res = mod->info->unload(); 00494 00495 if (res) { 00496 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00497 if (force <= AST_FORCE_FIRM) 00498 error = 1; 00499 else 00500 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00501 } 00502 } 00503 00504 if (!error) 00505 mod->flags.running = mod->flags.declined = 0; 00506 00507 AST_LIST_UNLOCK(&module_list); 00508 00509 if (!error && !mod->lib && mod->info && mod->info->restore_globals) 00510 mod->info->restore_globals(); 00511 00512 #ifdef LOADABLE_MODULES 00513 if (!error) 00514 unload_dynamic_module(mod); 00515 #endif 00516 00517 if (!error) 00518 ast_update_use_count(); 00519 00520 return res; 00521 }
int ast_update_module_list | ( | int(*)(const char *module, const char *description, int usecnt, const char *like) | modentry, | |
const char * | like | |||
) |
Ask for a list of modules, descriptions, and use counts.
modentry | A callback to an updater function. | |
like | For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module. |
Definition at line 1007 of file loader.c.
References AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_module_info::description, ast_module::info, ast_module::resource, and ast_module::usecount.
Referenced by handle_modlist(), and mod_update().
01009 { 01010 struct ast_module *cur; 01011 int unlock = -1; 01012 int total_mod_loaded = 0; 01013 01014 if (AST_LIST_TRYLOCK(&module_list)) 01015 unlock = 0; 01016 01017 AST_LIST_TRAVERSE(&module_list, cur, entry) { 01018 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 01019 } 01020 01021 if (unlock) 01022 AST_LIST_UNLOCK(&module_list); 01023 01024 return total_mod_loaded; 01025 }
void ast_update_use_count | ( | void | ) |
Notify when usecount has been changed.
This function calulates use counts and notifies anyone trying to keep track of them. It should be called whenever your module's usecount changes.
Definition at line 995 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and loadupdate::updater.
Referenced by __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), ast_module_ref(), ast_module_unref(), ast_unload_resource(), exit_now(), handle_request_do(), load_module(), load_resource(), oh323_request(), sip_request_call(), and unistim_new().
00996 { 00997 /* Notify any module monitors that the use count for a 00998 resource has changed */ 00999 struct loadupdate *m; 01000 01001 AST_LIST_LOCK(&updaters); 01002 AST_LIST_TRAVERSE(&updaters, m, entry) 01003 m->updater(); 01004 AST_LIST_UNLOCK(&updaters); 01005 }
static struct ast_module* find_resource | ( | const char * | resource, | |
int | do_lock | |||
) | [static] |
Definition at line 320 of file loader.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module_user::entry, ast_module::resource, and resource_name_match().
Referenced by ast_module_check(), ast_unload_resource(), and load_resource().
00321 { 00322 struct ast_module *cur; 00323 00324 if (do_lock) 00325 AST_LIST_LOCK(&module_list); 00326 00327 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00328 if (!resource_name_match(resource, cur->resource)) 00329 break; 00330 } 00331 00332 if (do_lock) 00333 AST_LIST_UNLOCK(&module_list); 00334 00335 return cur; 00336 }
static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 685 of file loader.c.
References ast_log(), ast_strlen_zero(), buildopt_sum, ast_module_info::buildopt_sum, ast_module_info::description, ast_module::info, ast_module_info::key, LOG_WARNING, ast_module::resource, and verify_key().
Referenced by load_resource().
00686 { 00687 if (!mod->info->description) { 00688 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00689 return 1; 00690 } 00691 00692 if (!mod->info->key) { 00693 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00694 return 1; 00695 } 00696 00697 if (verify_key((unsigned char *) mod->info->key)) { 00698 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00699 return 1; 00700 } 00701 00702 if (!ast_strlen_zero(mod->info->buildopt_sum) && 00703 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00704 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00705 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00706 return 1; 00707 } 00708 00709 return 0; 00710 }
static int key_matches | ( | const unsigned char * | key1, | |
const unsigned char * | key2 | |||
) | [static] |
Definition at line 273 of file loader.c.
Referenced by verify_key().
00274 { 00275 int x; 00276 00277 for (x = 0; x < 16; x++) { 00278 if (key1[x] != key2[x]) 00279 return 0; 00280 } 00281 00282 return 1; 00283 }
static struct ast_module* load_dynamic_module | ( | const char * | resource_in, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 351 of file loader.c.
References ast_calloc, ast_config_AST_MODULE_DIR, ast_free, AST_LIST_LAST, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, ast_test_flag, ast_module::info, ast_module::lib, LOG_WARNING, ast_module::resource, resource_being_loaded, RTLD_LOCAL, and RTLD_NOW.
Referenced by load_resource().
00352 { 00353 char fn[PATH_MAX] = ""; 00354 void *lib = NULL; 00355 struct ast_module *mod; 00356 unsigned int wants_global; 00357 int space; /* room needed for the descriptor */ 00358 int missing_so = 0; 00359 00360 space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1; 00361 if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) { 00362 missing_so = 1; 00363 space += 3; /* room for the extra ".so" */ 00364 } 00365 00366 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : ""); 00367 00368 /* make a first load of the module in 'quiet' mode... don't try to resolve 00369 any symbols, and don't export any symbols. this will allow us to peek into 00370 the module's info block (if available) to see what flags it has set */ 00371 00372 resource_being_loaded = ast_calloc(1, space); 00373 if (!resource_being_loaded) 00374 return NULL; 00375 strcpy(resource_being_loaded->resource, resource_in); 00376 if (missing_so) 00377 strcat(resource_being_loaded->resource, ".so"); 00378 00379 if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) { 00380 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00381 ast_free(resource_being_loaded); 00382 return NULL; 00383 } 00384 00385 /* the dlopen() succeeded, let's find out if the module 00386 registered itself */ 00387 /* note that this will only work properly as long as 00388 ast_module_register() (which is called by the module's 00389 constructor) places the new module at the tail of the 00390 module_list 00391 */ 00392 if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) { 00393 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in); 00394 /* no, it did not, so close it and return */ 00395 while (!dlclose(lib)); 00396 /* note that the module's destructor will call ast_module_unregister(), 00397 which will free the structure we allocated in resource_being_loaded */ 00398 return NULL; 00399 } 00400 00401 wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); 00402 00403 /* if we are being asked only to load modules that provide global symbols, 00404 and this one does not, then close it and return */ 00405 if (global_symbols_only && !wants_global) { 00406 while (!dlclose(lib)); 00407 return NULL; 00408 } 00409 00410 while (!dlclose(lib)); 00411 resource_being_loaded = NULL; 00412 00413 /* start the load process again */ 00414 resource_being_loaded = ast_calloc(1, space); 00415 if (!resource_being_loaded) 00416 return NULL; 00417 strcpy(resource_being_loaded->resource, resource_in); 00418 if (missing_so) 00419 strcat(resource_being_loaded->resource, ".so"); 00420 00421 if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) { 00422 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00423 ast_free(resource_being_loaded); 00424 return NULL; 00425 } 00426 00427 /* since the module was successfully opened, and it registered itself 00428 the previous time we did that, we're going to assume it worked this 00429 time too :) */ 00430 00431 AST_LIST_LAST(&module_list)->lib = lib; 00432 resource_being_loaded = NULL; 00433 00434 return AST_LIST_LAST(&module_list); 00435 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 822 of file loader.c.
References add_to_load_order(), ast_config_load, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verb, dir, embedding, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by main().
00823 { 00824 struct ast_config *cfg; 00825 struct ast_module *mod; 00826 struct load_order_entry *order; 00827 struct ast_variable *v; 00828 unsigned int load_count; 00829 struct load_order load_order; 00830 int res = 0; 00831 struct ast_flags config_flags = { 0 }; 00832 int modulecount = 0; 00833 00834 #ifdef LOADABLE_MODULES 00835 struct dirent *dirent; 00836 DIR *dir; 00837 #endif 00838 00839 /* all embedded modules have registered themselves by now */ 00840 embedding = 0; 00841 00842 ast_verb(1, "Asterisk Dynamic Loader Starting:\n"); 00843 00844 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00845 00846 AST_LIST_LOCK(&module_list); 00847 00848 if (embedded_module_list.first) { 00849 module_list.first = embedded_module_list.first; 00850 module_list.last = embedded_module_list.last; 00851 embedded_module_list.first = NULL; 00852 } 00853 00854 if (!(cfg = ast_config_load(AST_MODULE_CONFIG, config_flags))) { 00855 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00856 goto done; 00857 } 00858 00859 /* first, find all the modules we have been explicitly requested to load */ 00860 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00861 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) { 00862 add_to_load_order(v->value, &load_order); 00863 } 00864 } 00865 00866 /* check if 'autoload' is on */ 00867 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00868 /* if so, first add all the embedded modules that are not already running to the load order */ 00869 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00870 /* if it's not embedded, skip it */ 00871 if (mod->lib) 00872 continue; 00873 00874 if (mod->flags.running) 00875 continue; 00876 00877 order = add_to_load_order(mod->resource, &load_order); 00878 } 00879 00880 #ifdef LOADABLE_MODULES 00881 /* if we are allowed to load dynamic modules, scan the directory for 00882 for all available modules and add them as well */ 00883 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 00884 while ((dirent = readdir(dir))) { 00885 int ld = strlen(dirent->d_name); 00886 00887 /* Must end in .so to load it. */ 00888 00889 if (ld < 4) 00890 continue; 00891 00892 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 00893 continue; 00894 00895 /* if there is already a module by this name in the module_list, 00896 skip this file */ 00897 if (find_resource(dirent->d_name, 0)) 00898 continue; 00899 00900 add_to_load_order(dirent->d_name, &load_order); 00901 } 00902 00903 closedir(dir); 00904 } else { 00905 if (!ast_opt_quiet) 00906 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 00907 ast_config_AST_MODULE_DIR); 00908 } 00909 #endif 00910 } 00911 00912 /* now scan the config for any modules we are prohibited from loading and 00913 remove them from the load order */ 00914 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00915 if (strcasecmp(v->name, "noload")) 00916 continue; 00917 00918 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00919 if (!resource_name_match(order->resource, v->value)) { 00920 AST_LIST_REMOVE_CURRENT(entry); 00921 ast_free(order->resource); 00922 ast_free(order); 00923 } 00924 } 00925 AST_LIST_TRAVERSE_SAFE_END; 00926 } 00927 00928 /* we are done with the config now, all the information we need is in the 00929 load_order list */ 00930 ast_config_destroy(cfg); 00931 00932 load_count = 0; 00933 AST_LIST_TRAVERSE(&load_order, order, entry) 00934 load_count++; 00935 00936 if (load_count) 00937 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 00938 00939 /* first, load only modules that provide global symbols */ 00940 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00941 switch (load_resource(order->resource, 1)) { 00942 case AST_MODULE_LOAD_SUCCESS: 00943 modulecount++; 00944 case AST_MODULE_LOAD_DECLINE: 00945 AST_LIST_REMOVE_CURRENT(entry); 00946 ast_free(order->resource); 00947 ast_free(order); 00948 break; 00949 case AST_MODULE_LOAD_FAILURE: 00950 res = -1; 00951 goto done; 00952 case AST_MODULE_LOAD_SKIP: 00953 /* try again later */ 00954 break; 00955 } 00956 } 00957 AST_LIST_TRAVERSE_SAFE_END; 00958 00959 /* now load everything else */ 00960 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 00961 switch (load_resource(order->resource, 0)) { 00962 case AST_MODULE_LOAD_SUCCESS: 00963 modulecount++; 00964 case AST_MODULE_LOAD_DECLINE: 00965 AST_LIST_REMOVE_CURRENT(entry); 00966 ast_free(order->resource); 00967 ast_free(order); 00968 break; 00969 case AST_MODULE_LOAD_FAILURE: 00970 res = -1; 00971 goto done; 00972 case AST_MODULE_LOAD_SKIP: 00973 /* should not happen */ 00974 break; 00975 } 00976 } 00977 AST_LIST_TRAVERSE_SAFE_END; 00978 00979 done: 00980 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 00981 ast_free(order->resource); 00982 ast_free(order); 00983 } 00984 00985 AST_LIST_UNLOCK(&module_list); 00986 00987 /* Tell manager clients that are aggressive at logging in that we're done 00988 loading modules. If there's a DNS problem in chan_sip, we might not 00989 even reach this */ 00990 manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount); 00991 00992 return res; 00993 }
static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 712 of file loader.c.
References ast_fully_booted, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_test_flag, ast_update_use_count(), ast_verb, ast_verbose(), ast_module_info::backup_globals, COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module::lib, ast_module_info::load, load_dynamic_module(), LOG_WARNING, option_verbose, ast_module::running, term_color(), and unload_dynamic_module().
Referenced by ast_load_resource().
00713 { 00714 struct ast_module *mod; 00715 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00716 char tmp[256]; 00717 00718 if ((mod = find_resource(resource_name, 0))) { 00719 if (mod->flags.running) { 00720 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00721 return AST_MODULE_LOAD_DECLINE; 00722 } 00723 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00724 return AST_MODULE_LOAD_SKIP; 00725 } else { 00726 #ifdef LOADABLE_MODULES 00727 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00728 /* don't generate a warning message during load_modules() */ 00729 if (!global_symbols_only) { 00730 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00731 return AST_MODULE_LOAD_DECLINE; 00732 } else { 00733 return AST_MODULE_LOAD_SKIP; 00734 } 00735 } 00736 #else 00737 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00738 return AST_MODULE_LOAD_DECLINE; 00739 #endif 00740 } 00741 00742 if (inspect_module(mod)) { 00743 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00744 #ifdef LOADABLE_MODULES 00745 unload_dynamic_module(mod); 00746 #endif 00747 return AST_MODULE_LOAD_DECLINE; 00748 } 00749 00750 if (!mod->lib && mod->info->backup_globals()) { 00751 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name); 00752 return AST_MODULE_LOAD_DECLINE; 00753 } 00754 00755 mod->flags.declined = 0; 00756 00757 if (mod->info->load) 00758 res = mod->info->load(); 00759 00760 switch (res) { 00761 case AST_MODULE_LOAD_SUCCESS: 00762 if (!ast_fully_booted) { 00763 ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00764 if (ast_opt_console && !option_verbose) 00765 ast_verbose( "."); 00766 } else { 00767 ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description); 00768 } 00769 00770 mod->flags.running = 1; 00771 00772 ast_update_use_count(); 00773 break; 00774 case AST_MODULE_LOAD_DECLINE: 00775 mod->flags.declined = 1; 00776 break; 00777 case AST_MODULE_LOAD_FAILURE: 00778 break; 00779 case AST_MODULE_LOAD_SKIP: 00780 /* modules should never return this value */ 00781 break; 00782 } 00783 00784 return res; 00785 }
static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 260 of file loader.c.
References ast_debug, and buf.
Referenced by verify_key().
00261 { 00262 int x, pos; 00263 char buf[256]; /* large enough so we don't have to worry */ 00264 00265 for (pos = 0, x = 0; x < 16; x++) 00266 pos += sprintf(buf + pos, " %02x", *d++); 00267 00268 ast_debug(1, "Unexpected signature:%s\n", buf); 00269 00270 return 0; 00271 }
static void queue_reload_request | ( | const char * | module | ) | [static] |
Definition at line 580 of file loader.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), do_full_reload, ast_module_user::entry, LOG_ERROR, and reload_queue_item::module.
Referenced by ast_module_reload().
00581 { 00582 struct reload_queue_item *item; 00583 00584 AST_LIST_LOCK(&reload_queue); 00585 00586 if (do_full_reload) { 00587 AST_LIST_UNLOCK(&reload_queue); 00588 return; 00589 } 00590 00591 if (ast_strlen_zero(module)) { 00592 /* A full reload request (when module is NULL) wipes out any previous 00593 reload requests and causes the queue to ignore future ones */ 00594 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00595 ast_free(item); 00596 } 00597 do_full_reload = 1; 00598 } else { 00599 /* No reason to add the same module twice */ 00600 AST_LIST_TRAVERSE(&reload_queue, item, entry) { 00601 if (!strcasecmp(item->module, module)) { 00602 AST_LIST_UNLOCK(&reload_queue); 00603 return; 00604 } 00605 } 00606 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1); 00607 if (!item) { 00608 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n"); 00609 AST_LIST_UNLOCK(&reload_queue); 00610 return; 00611 } 00612 strcpy(item->module, module); 00613 AST_LIST_INSERT_TAIL(&reload_queue, item, entry); 00614 } 00615 AST_LIST_UNLOCK(&reload_queue); 00616 }
static int resource_name_match | ( | const char * | name1_in, | |
const char * | name2_in | |||
) | [static] |
Definition at line 302 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), and find_resource().
00303 { 00304 char *name1 = (char *) name1_in; 00305 char *name2 = (char *) name2_in; 00306 00307 /* trim off any .so extensions */ 00308 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00309 name1 = ast_strdupa(name1); 00310 name1[strlen(name1) - 3] = '\0'; 00311 } 00312 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00313 name2 = ast_strdupa(name2); 00314 name2[strlen(name2) - 3] = '\0'; 00315 } 00316 00317 return strcasecmp(name1, name2); 00318 }
static void unload_dynamic_module | ( | struct ast_module * | mod | ) | [static] |
Definition at line 339 of file loader.c.
References ast_module::lib.
Referenced by ast_unload_resource(), and load_resource().
00340 { 00341 void *lib = mod->lib; 00342 00343 /* WARNING: the structure pointed to by mod is going to 00344 disappear when this operation succeeds, so we can't 00345 dereference it */ 00346 00347 if (lib) 00348 while (!dlclose(lib)); 00349 }
static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 285 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00286 { 00287 struct MD5Context c; 00288 unsigned char digest[16]; 00289 00290 MD5Init(&c); 00291 MD5Update(&c, key, strlen((char *)key)); 00292 MD5Final(digest, &c); 00293 00294 if (key_matches(expected_key, digest)) 00295 return 0; 00296 00297 printdigest(digest); 00298 00299 return -1; 00300 }
char buildopt_sum[33] = AST_BUILDOPT_SUM [static] |
int do_full_reload = 0 [static] |
Definition at line 118 of file loader.c.
Referenced by ast_process_pending_reloads(), and queue_reload_request().
struct module_list embedded_module_list [static] |
unsigned int embedding = 1 [static] |
unsigned char expected_key[] [static] |
Initial value:
{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3, 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 }
Definition at line 71 of file loader.c.
Referenced by verify_key().
ast_mutex_t reloadlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
struct ast_module* resource_being_loaded |
Definition at line 126 of file loader.c.
Referenced by ast_module_register(), and load_dynamic_module().