2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
7 * Kevin P. Fleming <kpfleming@digium.com>
8 * Luigi Rizzo <rizzo@icir.org>
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
23 * \brief Module Loader
24 * \author Mark Spencer <markster@digium.com>
25 * \author Kevin P. Fleming <kpfleming@digium.com>
26 * \author Luigi Rizzo <rizzo@icir.org>
32 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
41 #include "asterisk/linkedlists.h"
42 #include "asterisk/module.h"
43 #include "asterisk/options.h"
44 #include "asterisk/config.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/term.h"
48 #include "asterisk/manager.h"
49 #include "asterisk/cdr.h"
50 #include "asterisk/enum.h"
51 #include "asterisk/rtp.h"
52 #include "asterisk/http.h"
53 #include "asterisk/lock.h"
57 #include "asterisk/md5.h"
58 #include "asterisk/utils.h"
64 struct ast_module_user
{
65 struct ast_channel
*chan
;
66 AST_LIST_ENTRY(ast_module_user
) entry
;
69 AST_LIST_HEAD(module_user_list
, ast_module_user
);
71 static unsigned char expected_key
[] =
72 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
73 0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
75 static char buildopt_sum
[33] = AST_BUILDOPT_SUM
;
77 static unsigned int embedding
= 1; /* we always start out by registering embedded modules,
78 since they are here before we dlopen() any
82 const struct ast_module_info
*info
;
83 void *lib
; /* the shared lib, or NULL if embedded */
84 int usecount
; /* the number of 'users' currently in this module */
85 struct module_user_list users
; /* the list of users in the module */
87 unsigned int running
:1;
88 unsigned int declined
:1;
90 AST_LIST_ENTRY(ast_module
) entry
;
94 static AST_LIST_HEAD_STATIC(module_list
, ast_module
);
98 AST_LIST_ENTRY(loadupdate
) entry
;
101 static AST_LIST_HEAD_STATIC(updaters
, loadupdate
);
103 AST_MUTEX_DEFINE_STATIC(reloadlock
);
105 /* when dynamic modules are being loaded, ast_module_register() will
106 need to know what filename the module was loaded from while it
109 struct ast_module
*resource_being_loaded
;
111 /* XXX: should we check for duplicate resource names here? */
113 void ast_module_register(const struct ast_module_info
*info
)
115 struct ast_module
*mod
;
118 if (!(mod
= ast_calloc(1, sizeof(*mod
) + strlen(info
->name
) + 1)))
120 strcpy(mod
->resource
, info
->name
);
122 mod
= resource_being_loaded
;
126 AST_LIST_HEAD_INIT(&mod
->users
);
128 /* during startup, before the loader has been initialized,
129 there are no threads, so there is no need to take the lock
130 on this list to manipulate it. it is also possible that it
131 might be unsafe to use the list lock at that point... so
132 let's avoid it altogether
135 AST_LIST_LOCK(&module_list
);
137 /* it is paramount that the new entry be placed at the tail of
138 the list, otherwise the code that uses dlopen() to load
139 dynamic modules won't be able to find out if the module it
140 just opened was registered or failed to load
142 AST_LIST_INSERT_TAIL(&module_list
, mod
, entry
);
145 AST_LIST_UNLOCK(&module_list
);
147 /* give the module a copy of its own handle, for later use in registrations and the like */
148 *((struct ast_module
**) &(info
->self
)) = mod
;
151 void ast_module_unregister(const struct ast_module_info
*info
)
153 struct ast_module
*mod
= NULL
;
155 /* it is assumed that the users list in the module structure
156 will already be empty, or we cannot have gotten to this
159 AST_LIST_LOCK(&module_list
);
160 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list
, mod
, entry
) {
161 if (mod
->info
== info
) {
162 AST_LIST_REMOVE_CURRENT(&module_list
, entry
);
166 AST_LIST_TRAVERSE_SAFE_END
;
167 AST_LIST_UNLOCK(&module_list
);
170 AST_LIST_HEAD_DESTROY(&mod
->users
);
175 struct ast_module_user
*__ast_module_user_add(struct ast_module
*mod
,
176 struct ast_channel
*chan
)
178 struct ast_module_user
*u
= ast_calloc(1, sizeof(*u
));
185 AST_LIST_LOCK(&mod
->users
);
186 AST_LIST_INSERT_HEAD(&mod
->users
, u
, entry
);
187 AST_LIST_UNLOCK(&mod
->users
);
189 ast_atomic_fetchadd_int(&mod
->usecount
, +1);
191 ast_update_use_count();
196 void __ast_module_user_remove(struct ast_module
*mod
, struct ast_module_user
*u
)
198 AST_LIST_LOCK(&mod
->users
);
199 AST_LIST_REMOVE(&mod
->users
, u
, entry
);
200 AST_LIST_UNLOCK(&mod
->users
);
201 ast_atomic_fetchadd_int(&mod
->usecount
, -1);
204 ast_update_use_count();
207 void __ast_module_user_hangup_all(struct ast_module
*mod
)
209 struct ast_module_user
*u
;
211 AST_LIST_LOCK(&mod
->users
);
212 while ((u
= AST_LIST_REMOVE_HEAD(&mod
->users
, entry
))) {
213 ast_softhangup(u
->chan
, AST_SOFTHANGUP_APPUNLOAD
);
214 ast_atomic_fetchadd_int(&mod
->usecount
, -1);
217 AST_LIST_UNLOCK(&mod
->users
);
219 ast_update_use_count();
223 * In addition to modules, the reload command handles some extra keywords
224 * which are listed here together with the corresponding handlers.
225 * This table is also used by the command completion code.
227 static struct reload_classes
{
229 int (*reload_fn
)(void);
230 } reload_classes
[] = { /* list in alpha order, longest match first for cli completion */
231 { "cdr", ast_cdr_engine_reload
},
232 { "dnsmgr", dnsmgr_reload
},
233 { "extconfig", read_config_maps
},
234 { "enum", ast_enum_reload
},
235 { "manager", reload_manager
},
236 { "rtp", ast_rtp_reload
},
237 { "http", ast_http_reload
},
238 { "logger", logger_reload
},
242 static int printdigest(const unsigned char *d
)
245 char buf
[256]; /* large enough so we don't have to worry */
247 for (pos
= 0, x
= 0; x
< 16; x
++)
248 pos
+= sprintf(buf
+ pos
, " %02x", *d
++);
250 ast_log(LOG_DEBUG
, "Unexpected signature:%s\n", buf
);
255 static int key_matches(const unsigned char *key1
, const unsigned char *key2
)
259 for (x
= 0; x
< 16; x
++) {
260 if (key1
[x
] != key2
[x
])
267 static int verify_key(const unsigned char *key
)
270 unsigned char digest
[16];
273 MD5Update(&c
, key
, strlen((char *)key
));
274 MD5Final(digest
, &c
);
276 if (key_matches(expected_key
, digest
))
284 static int resource_name_match(const char *name1_in
, const char *name2_in
)
286 char *name1
= (char *) name1_in
;
287 char *name2
= (char *) name2_in
;
289 /* trim off any .so extensions */
290 if (!strcasecmp(name1
+ strlen(name1
) - 3, ".so")) {
291 name1
= ast_strdupa(name1
);
292 name1
[strlen(name1
) - 3] = '\0';
294 if (!strcasecmp(name2
+ strlen(name2
) - 3, ".so")) {
295 name2
= ast_strdupa(name2
);
296 name2
[strlen(name2
) - 3] = '\0';
299 return strcasecmp(name1
, name2
);
302 static struct ast_module
*find_resource(const char *resource
, int do_lock
)
304 struct ast_module
*cur
;
307 AST_LIST_LOCK(&module_list
);
309 AST_LIST_TRAVERSE(&module_list
, cur
, entry
) {
310 if (!resource_name_match(resource
, cur
->resource
))
315 AST_LIST_UNLOCK(&module_list
);
320 #ifdef LOADABLE_MODULES
321 static void unload_dynamic_module(struct ast_module
*mod
)
323 void *lib
= mod
->lib
;
325 /* WARNING: the structure pointed to by mod is going to
326 disappear when this operation succeeds, so we can't
330 while (!dlclose(lib
));
333 static struct ast_module
*load_dynamic_module(const char *resource_in
, unsigned int global_symbols_only
)
337 struct ast_module
*mod
;
338 char *resource
= (char *) resource_in
;
339 unsigned int wants_global
;
341 if (strcasecmp(resource
+ strlen(resource
) - 3, ".so")) {
342 resource
= alloca(strlen(resource_in
) + 3);
343 strcpy(resource
, resource_in
);
344 strcat(resource
, ".so");
347 snprintf(fn
, sizeof(fn
), "%s/%s", ast_config_AST_MODULE_DIR
, resource
);
349 /* make a first load of the module in 'quiet' mode... don't try to resolve
350 any symbols, and don't export any symbols. this will allow us to peek into
351 the module's info block (if available) to see what flags it has set */
353 if (!(resource_being_loaded
= ast_calloc(1, sizeof(*resource_being_loaded
) + strlen(resource
) + 1)))
356 strcpy(resource_being_loaded
->resource
, resource
);
358 if (!(lib
= dlopen(fn
, RTLD_LAZY
| RTLD_LOCAL
))) {
359 ast_log(LOG_WARNING
, "Error loading module '%s': %s\n", resource_in
, dlerror());
360 free(resource_being_loaded
);
364 /* the dlopen() succeeded, let's find out if the module
366 /* note that this will only work properly as long as
367 ast_module_register() (which is called by the module's
368 constructor) places the new module at the tail of the
371 if (resource_being_loaded
!= (mod
= AST_LIST_LAST(&module_list
))) {
372 ast_log(LOG_WARNING
, "Module '%s' did not register itself during load\n", resource_in
);
373 /* no, it did not, so close it and return */
374 while (!dlclose(lib
));
375 /* note that the module's destructor will call ast_module_unregister(),
376 which will free the structure we allocated in resource_being_loaded */
380 wants_global
= ast_test_flag(mod
->info
, AST_MODFLAG_GLOBAL_SYMBOLS
);
382 /* if we are being asked only to load modules that provide global symbols,
383 and this one does not, then close it and return */
384 if (global_symbols_only
&& !wants_global
) {
385 while (!dlclose(lib
));
389 /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags
390 on the already-opened library to what we want... if not, we have to
391 close it and start over
393 #if defined(HAVE_RTLD_NOLOAD) && !defined(__Darwin__)
394 if (!dlopen(fn
, RTLD_NOLOAD
| (wants_global
? RTLD_LAZY
| RTLD_GLOBAL
: RTLD_NOW
| RTLD_LOCAL
))) {
395 ast_log(LOG_WARNING
, "Unable to promote flags on module '%s': %s\n", resource_in
, dlerror());
396 while (!dlclose(lib
));
397 free(resource_being_loaded
);
401 while (!dlclose(lib
));
402 resource_being_loaded
= NULL
;
404 /* start the load process again */
406 if (!(resource_being_loaded
= ast_calloc(1, sizeof(*resource_being_loaded
) + strlen(resource
) + 1)))
409 strcpy(resource_being_loaded
->resource
, resource
);
411 if (!(lib
= dlopen(fn
, wants_global
? RTLD_LAZY
| RTLD_GLOBAL
: RTLD_NOW
| RTLD_LOCAL
))) {
412 ast_log(LOG_WARNING
, "Error loading module '%s': %s\n", resource_in
, dlerror());
413 free(resource_being_loaded
);
417 /* since the module was successfully opened, and it registered itself
418 the previous time we did that, we're going to assume it worked this
422 AST_LIST_LAST(&module_list
)->lib
= lib
;
423 resource_being_loaded
= NULL
;
425 return AST_LIST_LAST(&module_list
);
429 void ast_module_shutdown(void)
431 struct ast_module
*mod
;
432 AST_LIST_HEAD_NOLOCK_STATIC(local_module_list
, ast_module
);
434 /* We have to call the unload() callbacks in reverse order that the modules
435 * exist in the module list so it is the reverse order of how they were
438 AST_LIST_LOCK(&module_list
);
439 while ((mod
= AST_LIST_REMOVE_HEAD(&module_list
, entry
)))
440 AST_LIST_INSERT_HEAD(&local_module_list
, mod
, entry
);
441 AST_LIST_UNLOCK(&module_list
);
443 while ((mod
= AST_LIST_REMOVE_HEAD(&local_module_list
, entry
))) {
444 if (mod
->info
->unload
)
446 /* Since this should only be called when shutting down "gracefully",
447 * all channels should be down before we get to this point, meaning
448 * there will be no module users left. */
449 AST_LIST_HEAD_DESTROY(&mod
->users
);
454 int ast_unload_resource(const char *resource_name
, enum ast_module_unload_mode force
)
456 struct ast_module
*mod
;
460 AST_LIST_LOCK(&module_list
);
462 if (!(mod
= find_resource(resource_name
, 0))) {
463 AST_LIST_UNLOCK(&module_list
);
467 if (!(mod
->flags
.running
|| mod
->flags
.declined
))
471 ast_log(LOG_WARNING
, "Unloading embedded modules is not supported.\n");
475 if (!error
&& (mod
->usecount
> 0)) {
477 ast_log(LOG_WARNING
, "Warning: Forcing removal of module '%s' with use count %d\n",
478 resource_name
, mod
->usecount
);
480 ast_log(LOG_WARNING
, "Soft unload failed, '%s' has use count %d\n", resource_name
,
487 __ast_module_user_hangup_all(mod
);
488 res
= mod
->info
->unload();
491 ast_log(LOG_WARNING
, "Firm unload failed for %s\n", resource_name
);
492 if (force
<= AST_FORCE_FIRM
)
495 ast_log(LOG_WARNING
, "** Dangerous **: Unloading resource anyway, at user request\n");
500 mod
->flags
.running
= mod
->flags
.declined
= 0;
502 AST_LIST_UNLOCK(&module_list
);
504 #ifdef LOADABLE_MODULES
506 unload_dynamic_module(mod
);
510 ast_update_use_count();
515 char *ast_module_helper(const char *line
, const char *word
, int pos
, int state
, int rpos
, int needsreload
)
517 struct ast_module
*cur
;
518 int i
, which
=0, l
= strlen(word
);
524 AST_LIST_LOCK(&module_list
);
525 AST_LIST_TRAVERSE(&module_list
, cur
, entry
) {
526 if (!strncasecmp(word
, cur
->resource
, l
) &&
527 (cur
->info
->reload
|| !needsreload
) &&
529 ret
= strdup(cur
->resource
);
533 AST_LIST_UNLOCK(&module_list
);
536 for (i
=0; !ret
&& reload_classes
[i
].name
; i
++) {
537 if (!strncasecmp(word
, reload_classes
[i
].name
, l
) && ++which
> state
)
538 ret
= strdup(reload_classes
[i
].name
);
545 int ast_module_reload(const char *name
)
547 struct ast_module
*cur
;
548 int res
= 0; /* return value. 0 = not found, others, see below */
551 if (ast_mutex_trylock(&reloadlock
)) {
552 ast_verbose("The previous reload command didn't finish yet\n");
553 return -1; /* reload already in progress */
555 ast_lastreloadtime
= time(NULL
);
557 /* Call "predefined" reload here first */
558 for (i
= 0; reload_classes
[i
].name
; i
++) {
559 if (!name
|| !strcasecmp(name
, reload_classes
[i
].name
)) {
560 reload_classes
[i
].reload_fn(); /* XXX should check error ? */
561 res
= 2; /* found and reloaded */
566 ast_mutex_unlock(&reloadlock
);
570 AST_LIST_LOCK(&module_list
);
571 AST_LIST_TRAVERSE(&module_list
, cur
, entry
) {
572 const struct ast_module_info
*info
= cur
->info
;
574 if (name
&& resource_name_match(name
, cur
->resource
))
577 if (!cur
->flags
.running
|| cur
->flags
.declined
) {
580 ast_log(LOG_NOTICE
, "The module '%s' was not properly initialized. "
581 "Before reloading the module, you must run \"module load %s\" "
582 "and fix whatever is preventing the module from being initialized.\n",
584 res
= 2; /* Don't report that the module was not found */
588 if (!info
->reload
) { /* cannot be reloaded */
589 if (res
< 1) /* store result if possible */
590 res
= 1; /* 1 = no reload() method */
595 if (option_verbose
> 2)
596 ast_verbose(VERBOSE_PREFIX_3
"Reloading module '%s' (%s)\n", cur
->resource
, info
->description
);
599 AST_LIST_UNLOCK(&module_list
);
601 ast_mutex_unlock(&reloadlock
);
606 static unsigned int inspect_module(const struct ast_module
*mod
)
608 if (!mod
->info
->description
) {
609 ast_log(LOG_WARNING
, "Module '%s' does not provide a description.\n", mod
->resource
);
613 if (!mod
->info
->key
) {
614 ast_log(LOG_WARNING
, "Module '%s' does not provide a license key.\n", mod
->resource
);
618 if (verify_key((unsigned char *) mod
->info
->key
)) {
619 ast_log(LOG_WARNING
, "Module '%s' did not provide a valid license key.\n", mod
->resource
);
623 if (!ast_test_flag(mod
->info
, AST_MODFLAG_BUILDSUM
)) {
624 ast_log(LOG_WARNING
, "Module '%s' was not compiled against a recent version of Asterisk and may cause instability.\n", mod
->resource
);
625 } else if (!ast_strlen_zero(mod
->info
->buildopt_sum
) &&
626 strcmp(buildopt_sum
, mod
->info
->buildopt_sum
)) {
627 ast_log(LOG_WARNING
, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod
->resource
);
628 ast_log(LOG_WARNING
, "Module '%s' will not be initialized as it may cause instability.\n", mod
->resource
);
635 static enum ast_module_load_result
load_resource(const char *resource_name
, unsigned int global_symbols_only
)
637 struct ast_module
*mod
;
638 enum ast_module_load_result res
= AST_MODULE_LOAD_SUCCESS
;
641 if ((mod
= find_resource(resource_name
, 0))) {
642 if (mod
->flags
.running
) {
643 ast_log(LOG_WARNING
, "Module '%s' already exists.\n", resource_name
);
644 return AST_MODULE_LOAD_DECLINE
;
646 if (global_symbols_only
&& !ast_test_flag(mod
->info
, AST_MODFLAG_GLOBAL_SYMBOLS
))
647 return AST_MODULE_LOAD_SKIP
;
649 #ifdef LOADABLE_MODULES
650 if (!(mod
= load_dynamic_module(resource_name
, global_symbols_only
))) {
651 /* don't generate a warning message during load_modules() */
652 if (!global_symbols_only
) {
653 ast_log(LOG_WARNING
, "Module '%s' could not be loaded.\n", resource_name
);
654 return AST_MODULE_LOAD_DECLINE
;
656 return AST_MODULE_LOAD_SKIP
;
660 ast_log(LOG_WARNING
, "Module '%s' could not be loaded.\n", resource_name
);
661 return AST_MODULE_LOAD_DECLINE
;
665 if (inspect_module(mod
)) {
666 ast_log(LOG_WARNING
, "Module '%s' could not be loaded.\n", resource_name
);
667 #ifdef LOADABLE_MODULES
668 unload_dynamic_module(mod
);
670 return AST_MODULE_LOAD_DECLINE
;
673 mod
->flags
.declined
= 0;
676 res
= mod
->info
->load();
679 case AST_MODULE_LOAD_SUCCESS
:
680 if (!ast_fully_booted
) {
682 ast_verbose("%s => (%s)\n", resource_name
, term_color(tmp
, mod
->info
->description
, COLOR_BROWN
, COLOR_BLACK
, sizeof(tmp
)));
683 if (ast_opt_console
&& !option_verbose
)
687 ast_verbose(VERBOSE_PREFIX_1
"Loaded %s => (%s)\n", resource_name
, mod
->info
->description
);
690 mod
->flags
.running
= 1;
692 ast_update_use_count();
694 case AST_MODULE_LOAD_DECLINE
:
695 mod
->flags
.declined
= 1;
697 case AST_MODULE_LOAD_FAILURE
:
699 case AST_MODULE_LOAD_SKIP
:
700 /* modules should never return this value */
707 int ast_load_resource(const char *resource_name
)
709 AST_LIST_LOCK(&module_list
);
710 load_resource(resource_name
, 0);
711 AST_LIST_UNLOCK(&module_list
);
716 struct load_order_entry
{
718 AST_LIST_ENTRY(load_order_entry
) entry
;
721 AST_LIST_HEAD_NOLOCK(load_order
, load_order_entry
);
723 static struct load_order_entry
*add_to_load_order(const char *resource
, struct load_order
*load_order
)
725 struct load_order_entry
*order
;
727 AST_LIST_TRAVERSE(load_order
, order
, entry
) {
728 if (!resource_name_match(order
->resource
, resource
))
732 if (!(order
= ast_calloc(1, sizeof(*order
))))
735 order
->resource
= ast_strdup(resource
);
736 AST_LIST_INSERT_TAIL(load_order
, order
, entry
);
741 static int translate_module_name(char *oldname
, char *newname
)
743 if (!strcasecmp(oldname
, "app_zapbarge.so"))
744 ast_copy_string(newname
, "app_dahdibarge.so", 18);
745 else if(!strcasecmp(oldname
, "app_zapras.so"))
746 ast_copy_string(newname
, "app_dahdiras.so", 16);
747 else if(!strcasecmp(oldname
, "app_zapscan.so"))
748 ast_copy_string(newname
, "app_dahdiscan.so", 17);
749 else if(!strcasecmp(oldname
, "codec_zap.so"))
750 ast_copy_string(newname
, "codec_dahdi.so", 16);
752 return -1; /* no use for newname, oldname is fine */
758 int load_modules(unsigned int preload_only
)
760 struct ast_config
*cfg
;
761 struct ast_module
*mod
;
762 struct load_order_entry
*order
;
763 struct ast_variable
*v
;
764 unsigned int load_count
;
765 struct load_order load_order
;
768 int translate_status
;
769 char newname
[18]; /* although this would normally be 80, max length in translate_module_name is 18 */
770 #ifdef LOADABLE_MODULES
771 struct dirent
*dirent
;
775 /* all embedded modules have registered themselves by now */
779 ast_verbose("Asterisk Dynamic Loader Starting:\n");
781 AST_LIST_HEAD_INIT_NOLOCK(&load_order
);
783 AST_LIST_LOCK(&module_list
);
785 if (!(cfg
= ast_config_load(AST_MODULE_CONFIG
))) {
786 ast_log(LOG_WARNING
, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG
);
790 /* first, find all the modules we have been explicitly requested to load */
791 for (v
= ast_variable_browse(cfg
, "modules"); v
; v
= v
->next
) {
792 if (!strcasecmp(v
->name
, preload_only
? "preload" : "load")) {
793 translate_status
= translate_module_name(v
->value
, newname
);
794 if (!translate_status
)
795 ast_log(LOG_WARNING
, "Use of old module name %s is deprecated, please use %s instead.\n", v
->value
, newname
);
796 add_to_load_order(translate_status
? v
->value
: newname
, &load_order
);
800 /* check if 'autoload' is on */
801 if (!preload_only
&& ast_true(ast_variable_retrieve(cfg
, "modules", "autoload"))) {
802 /* if so, first add all the embedded modules that are not already running to the load order */
803 AST_LIST_TRAVERSE(&module_list
, mod
, entry
) {
804 /* if it's not embedded, skip it */
808 if (mod
->flags
.running
)
811 order
= add_to_load_order(mod
->resource
, &load_order
);
814 #ifdef LOADABLE_MODULES
815 /* if we are allowed to load dynamic modules, scan the directory for
816 for all available modules and add them as well */
817 if ((dir
= opendir(ast_config_AST_MODULE_DIR
))) {
818 while ((dirent
= readdir(dir
))) {
819 int ld
= strlen(dirent
->d_name
);
821 /* Must end in .so to load it. */
826 if (strcasecmp(dirent
->d_name
+ ld
- 3, ".so"))
829 /* if there is already a module by this name in the module_list,
831 if (find_resource(dirent
->d_name
, 0))
834 add_to_load_order(dirent
->d_name
, &load_order
);
840 ast_log(LOG_WARNING
, "Unable to open modules directory '%s'.\n",
841 ast_config_AST_MODULE_DIR
);
846 /* now scan the config for any modules we are prohibited from loading and
847 remove them from the load order */
848 for (v
= ast_variable_browse(cfg
, "modules"); v
; v
= v
->next
) {
849 if (strcasecmp(v
->name
, "noload"))
852 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order
, order
, entry
) {
853 translate_status
= translate_module_name(v
->value
, newname
);
854 if (!resource_name_match(order
->resource
, translate_status
? v
->value
: newname
)) {
855 if (!translate_status
)
856 ast_log(LOG_WARNING
, "Use of old module name %s is deprecated, please use %s instead.\n", v
->value
, newname
);
857 AST_LIST_REMOVE_CURRENT(&load_order
, entry
);
858 free(order
->resource
);
862 AST_LIST_TRAVERSE_SAFE_END
;
865 /* we are done with the config now, all the information we need is in the
867 ast_config_destroy(cfg
);
870 AST_LIST_TRAVERSE(&load_order
, order
, entry
)
874 ast_log(LOG_NOTICE
, "%d modules will be loaded.\n", load_count
);
876 /* first, load only modules that provide global symbols */
877 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order
, order
, entry
) {
878 switch (load_resource(order
->resource
, 1)) {
879 case AST_MODULE_LOAD_SUCCESS
:
880 case AST_MODULE_LOAD_DECLINE
:
881 AST_LIST_REMOVE_CURRENT(&load_order
, entry
);
882 free(order
->resource
);
885 case AST_MODULE_LOAD_FAILURE
:
888 case AST_MODULE_LOAD_SKIP
:
889 /* try again later */
893 AST_LIST_TRAVERSE_SAFE_END
;
895 /* now load everything else */
896 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order
, order
, entry
) {
897 switch (load_resource(order
->resource
, 0)) {
898 case AST_MODULE_LOAD_SUCCESS
:
899 case AST_MODULE_LOAD_DECLINE
:
900 AST_LIST_REMOVE_CURRENT(&load_order
, entry
);
901 free(order
->resource
);
904 case AST_MODULE_LOAD_FAILURE
:
907 case AST_MODULE_LOAD_SKIP
:
908 /* should not happen */
912 AST_LIST_TRAVERSE_SAFE_END
;
915 while ((order
= AST_LIST_REMOVE_HEAD(&load_order
, entry
))) {
916 free(order
->resource
);
920 AST_LIST_UNLOCK(&module_list
);
925 void ast_update_use_count(void)
927 /* Notify any module monitors that the use count for a
928 resource has changed */
929 struct loadupdate
*m
;
931 AST_LIST_LOCK(&updaters
);
932 AST_LIST_TRAVERSE(&updaters
, m
, entry
)
934 AST_LIST_UNLOCK(&updaters
);
937 int ast_update_module_list(int (*modentry
)(const char *module
, const char *description
, int usecnt
, const char *like
),
940 struct ast_module
*cur
;
942 int total_mod_loaded
= 0;
944 if (AST_LIST_TRYLOCK(&module_list
))
947 AST_LIST_TRAVERSE(&module_list
, cur
, entry
) {
948 total_mod_loaded
+= modentry(cur
->resource
, cur
->info
->description
, cur
->usecount
, like
);
952 AST_LIST_UNLOCK(&module_list
);
954 return total_mod_loaded
;
957 int ast_loader_register(int (*v
)(void))
959 struct loadupdate
*tmp
;
961 if (!(tmp
= ast_malloc(sizeof(*tmp
))))
965 AST_LIST_LOCK(&updaters
);
966 AST_LIST_INSERT_HEAD(&updaters
, tmp
, entry
);
967 AST_LIST_UNLOCK(&updaters
);
972 int ast_loader_unregister(int (*v
)(void))
974 struct loadupdate
*cur
;
976 AST_LIST_LOCK(&updaters
);
977 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters
, cur
, entry
) {
978 if (cur
->updater
== v
) {
979 AST_LIST_REMOVE_CURRENT(&updaters
, entry
);
983 AST_LIST_TRAVERSE_SAFE_END
;
984 AST_LIST_UNLOCK(&updaters
);
989 struct ast_module
*ast_module_ref(struct ast_module
*mod
)
991 ast_atomic_fetchadd_int(&mod
->usecount
, +1);
992 ast_update_use_count();
997 void ast_module_unref(struct ast_module
*mod
)
999 ast_atomic_fetchadd_int(&mod
->usecount
, -1);
1000 ast_update_use_count();