Conditionally load the AGI command gosub, depending on whether or not res_agi
[asterisk/asterisk.git] / main / loader.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  * Kevin P. Fleming <kpfleming@digium.com>
8  * Luigi Rizzo <rizzo@icir.org>
9  *
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.
15  *
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.
19  */
20
21 /*! \file
22  *
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>
27  * - See ModMngMnt
28  */
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/_private.h"
35 #include "asterisk/paths.h"     /* use ast_config_AST_MODULE_DIR */
36 #include <dirent.h>
37
38 #include "asterisk/linkedlists.h"
39 #include "asterisk/module.h"
40 #include "asterisk/config.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/term.h"
43 #include "asterisk/manager.h"
44 #include "asterisk/cdr.h"
45 #include "asterisk/enum.h"
46 #include "asterisk/rtp.h"
47 #include "asterisk/http.h"
48 #include "asterisk/lock.h"
49 #include "asterisk/features.h"
50 #include "asterisk/dsp.h"
51 #include "asterisk/udptl.h"
52
53 #ifdef DLFCNCOMPAT
54 #include "asterisk/dlfcn-compat.h"
55 #else
56 #include <dlfcn.h>
57 #endif
58
59 #include "asterisk/md5.h"
60 #include "asterisk/utils.h"
61
62 #ifndef RTLD_NOW
63 #define RTLD_NOW 0
64 #endif
65
66 #ifndef RTLD_LOCAL
67 #define RTLD_LOCAL 0
68 #endif
69
70 struct ast_module_user {
71         struct ast_channel *chan;
72         AST_LIST_ENTRY(ast_module_user) entry;
73 };
74
75 AST_LIST_HEAD(module_user_list, ast_module_user);
76
77 static unsigned char expected_key[] =
78 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
79   0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
80
81 static char buildopt_sum[33] = AST_BUILDOPT_SUM;
82
83 static unsigned int embedding = 1; /* we always start out by registering embedded modules,
84                                       since they are here before we dlopen() any
85                                    */
86
87 struct ast_module {
88         const struct ast_module_info *info;
89         void *lib;                                      /* the shared lib, or NULL if embedded */
90         int usecount;                                   /* the number of 'users' currently in this module */
91         struct module_user_list users;                  /* the list of users in the module */
92         struct {
93                 unsigned int running:1;
94                 unsigned int declined:1;
95         } flags;
96         AST_LIST_ENTRY(ast_module) entry;
97         char resource[0];
98 };
99
100 static AST_LIST_HEAD_STATIC(module_list, ast_module);
101
102 /*
103  * module_list is cleared by its constructor possibly after
104  * we start accumulating embedded modules, so we need to
105  * use another list (without the lock) to accumulate them.
106  * Then we update the main list when embedding is done.
107  */
108 static struct module_list embedded_module_list;
109
110 struct loadupdate {
111         int (*updater)(void);
112         AST_LIST_ENTRY(loadupdate) entry;
113 };
114
115 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
116
117 AST_MUTEX_DEFINE_STATIC(reloadlock);
118
119 /* when dynamic modules are being loaded, ast_module_register() will
120    need to know what filename the module was loaded from while it
121    is being registered
122 */
123 struct ast_module *resource_being_loaded;
124
125 /* XXX: should we check for duplicate resource names here? */
126
127 void ast_module_register(const struct ast_module_info *info)
128 {
129         struct ast_module *mod;
130
131         if (embedding) {
132                 if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
133                         return;
134                 strcpy(mod->resource, info->name);
135         } else {
136                 mod = resource_being_loaded;
137         }
138
139         mod->info = info;
140         AST_LIST_HEAD_INIT(&mod->users);
141
142         /* during startup, before the loader has been initialized,
143            there are no threads, so there is no need to take the lock
144            on this list to manipulate it. it is also possible that it
145            might be unsafe to use the list lock at that point... so
146            let's avoid it altogether
147         */
148         if (embedding) {
149                 AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
150         } else {
151                 AST_LIST_LOCK(&module_list);
152                 /* it is paramount that the new entry be placed at the tail of
153                    the list, otherwise the code that uses dlopen() to load
154                    dynamic modules won't be able to find out if the module it
155                    just opened was registered or failed to load
156                 */
157                 AST_LIST_INSERT_TAIL(&module_list, mod, entry);
158                 AST_LIST_UNLOCK(&module_list);
159         }
160
161         /* give the module a copy of its own handle, for later use in registrations and the like */
162         *((struct ast_module **) &(info->self)) = mod;
163 }
164
165 void ast_module_unregister(const struct ast_module_info *info)
166 {
167         struct ast_module *mod = NULL;
168
169         /* it is assumed that the users list in the module structure
170            will already be empty, or we cannot have gotten to this
171            point
172         */
173         AST_LIST_LOCK(&module_list);
174         AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
175                 if (mod->info == info) {
176                         AST_LIST_REMOVE_CURRENT(entry);
177                         break;
178                 }
179         }
180         AST_LIST_TRAVERSE_SAFE_END;
181         AST_LIST_UNLOCK(&module_list);
182
183         if (mod) {
184                 AST_LIST_HEAD_DESTROY(&mod->users);
185                 ast_free(mod);
186         }
187 }
188
189 struct ast_module_user *__ast_module_user_add(struct ast_module *mod,
190                                               struct ast_channel *chan)
191 {
192         struct ast_module_user *u = ast_calloc(1, sizeof(*u));
193
194         if (!u)
195                 return NULL;
196
197         u->chan = chan;
198
199         AST_LIST_LOCK(&mod->users);
200         AST_LIST_INSERT_HEAD(&mod->users, u, entry);
201         AST_LIST_UNLOCK(&mod->users);
202
203         ast_atomic_fetchadd_int(&mod->usecount, +1);
204
205         ast_update_use_count();
206
207         return u;
208 }
209
210 void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
211 {
212         AST_LIST_LOCK(&mod->users);
213         AST_LIST_REMOVE(&mod->users, u, entry);
214         AST_LIST_UNLOCK(&mod->users);
215         ast_atomic_fetchadd_int(&mod->usecount, -1);
216         ast_free(u);
217
218         ast_update_use_count();
219 }
220
221 void __ast_module_user_hangup_all(struct ast_module *mod)
222 {
223         struct ast_module_user *u;
224
225         AST_LIST_LOCK(&mod->users);
226         while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
227                 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
228                 ast_atomic_fetchadd_int(&mod->usecount, -1);
229                 ast_free(u);
230         }
231         AST_LIST_UNLOCK(&mod->users);
232
233         ast_update_use_count();
234 }
235
236 /*! \note
237  * In addition to modules, the reload command handles some extra keywords
238  * which are listed here together with the corresponding handlers.
239  * This table is also used by the command completion code.
240  */
241 static struct reload_classes {
242         const char *name;
243         int (*reload_fn)(void);
244 } reload_classes[] = {  /* list in alpha order, longest match first for cli completion */
245         { "cdr",        ast_cdr_engine_reload },
246         { "dnsmgr",     dnsmgr_reload },
247         { "extconfig",  read_config_maps },
248         { "enum",       ast_enum_reload },
249         { "manager",    reload_manager },
250         { "rtp",        ast_rtp_reload },
251         { "http",       ast_http_reload },
252         { "logger",     logger_reload },
253         { "features",   ast_features_reload },
254         { "dsp",        ast_dsp_reload},
255         { "udptl",      ast_udptl_reload },
256         { NULL,         NULL }
257 };
258
259 static int printdigest(const unsigned char *d)
260 {
261         int x, pos;
262         char buf[256]; /* large enough so we don't have to worry */
263
264         for (pos = 0, x = 0; x < 16; x++)
265                 pos += sprintf(buf + pos, " %02x", *d++);
266
267         ast_debug(1, "Unexpected signature:%s\n", buf);
268
269         return 0;
270 }
271
272 static int key_matches(const unsigned char *key1, const unsigned char *key2)
273 {
274         int x;
275
276         for (x = 0; x < 16; x++) {
277                 if (key1[x] != key2[x])
278                         return 0;
279         }
280
281         return 1;
282 }
283
284 static int verify_key(const unsigned char *key)
285 {
286         struct MD5Context c;
287         unsigned char digest[16];
288
289         MD5Init(&c);
290         MD5Update(&c, key, strlen((char *)key));
291         MD5Final(digest, &c);
292
293         if (key_matches(expected_key, digest))
294                 return 0;
295
296         printdigest(digest);
297
298         return -1;
299 }
300
301 static int resource_name_match(const char *name1_in, const char *name2_in)
302 {
303         char *name1 = (char *) name1_in;
304         char *name2 = (char *) name2_in;
305
306         /* trim off any .so extensions */
307         if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
308                 name1 = ast_strdupa(name1);
309                 name1[strlen(name1) - 3] = '\0';
310         }
311         if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
312                 name2 = ast_strdupa(name2);
313                 name2[strlen(name2) - 3] = '\0';
314         }
315
316         return strcasecmp(name1, name2);
317 }
318
319 static struct ast_module *find_resource(const char *resource, int do_lock)
320 {
321         struct ast_module *cur;
322
323         if (do_lock)
324                 AST_LIST_LOCK(&module_list);
325
326         AST_LIST_TRAVERSE(&module_list, cur, entry) {
327                 if (!resource_name_match(resource, cur->resource))
328                         break;
329         }
330
331         if (do_lock)
332                 AST_LIST_UNLOCK(&module_list);
333
334         return cur;
335 }
336
337 #ifdef LOADABLE_MODULES
338 static void unload_dynamic_module(struct ast_module *mod)
339 {
340         void *lib = mod->lib;
341
342         /* WARNING: the structure pointed to by mod is going to
343            disappear when this operation succeeds, so we can't
344            dereference it */
345
346         if (lib)
347                 while (!dlclose(lib));
348 }
349
350 static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only)
351 {
352         char fn[PATH_MAX] = "";
353         void *lib = NULL;
354         struct ast_module *mod;
355         unsigned int wants_global;
356         int space;      /* room needed for the descriptor */
357         int missing_so = 0;
358
359         space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
360         if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
361                 missing_so = 1;
362                 space += 3;     /* room for the extra ".so" */
363         }
364
365         snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
366
367         /* make a first load of the module in 'quiet' mode... don't try to resolve
368            any symbols, and don't export any symbols. this will allow us to peek into
369            the module's info block (if available) to see what flags it has set */
370
371         resource_being_loaded = ast_calloc(1, space);
372         if (!resource_being_loaded)
373                 return NULL;
374         strcpy(resource_being_loaded->resource, resource_in);
375         if (missing_so)
376                 strcat(resource_being_loaded->resource, ".so");
377
378         if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
379                 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
380                 ast_free(resource_being_loaded);
381                 return NULL;
382         }
383
384         /* the dlopen() succeeded, let's find out if the module
385            registered itself */
386         /* note that this will only work properly as long as
387            ast_module_register() (which is called by the module's
388            constructor) places the new module at the tail of the
389            module_list
390         */
391         if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
392                 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
393                 /* no, it did not, so close it and return */
394                 while (!dlclose(lib));
395                 /* note that the module's destructor will call ast_module_unregister(),
396                    which will free the structure we allocated in resource_being_loaded */
397                 return NULL;
398         }
399
400         wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
401
402         /* if we are being asked only to load modules that provide global symbols,
403            and this one does not, then close it and return */
404         if (global_symbols_only && !wants_global) {
405                 while (!dlclose(lib));
406                 return NULL;
407         }
408
409         /* if the system supports RTLD_NOLOAD, we can just 'promote' the flags
410            on the already-opened library to what we want... if not, we have to
411            close it and start over
412         */
413 #if defined(HAVE_RTLD_NOLOAD) && !defined(__Darwin__)
414         if (!dlopen(fn, RTLD_NOLOAD | (wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
415                 ast_log(LOG_WARNING, "Unable to promote flags on module '%s': %s\n", resource_in, dlerror());
416                 while (!dlclose(lib));
417                 ast_free(resource_being_loaded);
418                 return NULL;
419         }
420 #else
421         while (!dlclose(lib));
422         resource_being_loaded = NULL;
423
424         /* start the load process again */
425         resource_being_loaded = ast_calloc(1, space);
426         if (!resource_being_loaded)
427                 return NULL;
428         strcpy(resource_being_loaded->resource, resource_in);
429         if (missing_so)
430                 strcat(resource_being_loaded->resource, ".so");
431
432         if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
433                 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
434                 ast_free(resource_being_loaded);
435                 return NULL;
436         }
437
438         /* since the module was successfully opened, and it registered itself
439            the previous time we did that, we're going to assume it worked this
440            time too :) */
441 #endif
442
443         AST_LIST_LAST(&module_list)->lib = lib;
444         resource_being_loaded = NULL;
445
446         return AST_LIST_LAST(&module_list);
447 }
448 #endif
449
450 void ast_module_shutdown(void)
451 {
452         struct ast_module *mod;
453         AST_LIST_HEAD_NOLOCK_STATIC(local_module_list, ast_module);
454
455         /* We have to call the unload() callbacks in reverse order that the modules
456          * exist in the module list so it is the reverse order of how they were
457          * loaded. */
458
459         AST_LIST_LOCK(&module_list);
460         while ((mod = AST_LIST_REMOVE_HEAD(&module_list, entry)))
461                 AST_LIST_INSERT_HEAD(&local_module_list, mod, entry);
462         AST_LIST_UNLOCK(&module_list);
463
464         while ((mod = AST_LIST_REMOVE_HEAD(&local_module_list, entry))) {
465                 if (mod->info->unload)
466                         mod->info->unload();
467                 /* Since this should only be called when shutting down "gracefully",
468                  * all channels should be down before we get to this point, meaning
469                  * there will be no module users left. */
470                 AST_LIST_HEAD_DESTROY(&mod->users);
471                 free(mod);
472         }
473 }
474
475 int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode force)
476 {
477         struct ast_module *mod;
478         int res = -1;
479         int error = 0;
480
481         AST_LIST_LOCK(&module_list);
482
483         if (!(mod = find_resource(resource_name, 0))) {
484                 AST_LIST_UNLOCK(&module_list);
485                 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
486                 return 0;
487         }
488
489         if (!(mod->flags.running || mod->flags.declined))
490                 error = 1;
491
492         if (!error && (mod->usecount > 0)) {
493                 if (force)
494                         ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
495                                 resource_name, mod->usecount);
496                 else {
497                         ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
498                                 mod->usecount);
499                         error = 1;
500                 }
501         }
502
503         if (!error) {
504                 __ast_module_user_hangup_all(mod);
505                 res = mod->info->unload();
506
507                 if (res) {
508                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
509                         if (force <= AST_FORCE_FIRM)
510                                 error = 1;
511                         else
512                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
513                 }
514         }
515
516         if (!error)
517                 mod->flags.running = mod->flags.declined = 0;
518
519         AST_LIST_UNLOCK(&module_list);
520
521         if (!error && !mod->lib && mod->info && mod->info->restore_globals)
522                 mod->info->restore_globals();
523
524 #ifdef LOADABLE_MODULES
525         if (!error)
526                 unload_dynamic_module(mod);
527 #endif
528
529         if (!error)
530                 ast_update_use_count();
531
532         return res;
533 }
534
535 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
536 {
537         struct ast_module *cur;
538         int i, which=0, l = strlen(word);
539         char *ret = NULL;
540
541         if (pos != rpos)
542                 return NULL;
543
544         AST_LIST_LOCK(&module_list);
545         AST_LIST_TRAVERSE(&module_list, cur, entry) {
546                 if (!strncasecmp(word, cur->resource, l) &&
547                     (cur->info->reload || !needsreload) &&
548                     ++which > state) {
549                         ret = ast_strdup(cur->resource);
550                         break;
551                 }
552         }
553         AST_LIST_UNLOCK(&module_list);
554
555         if (!ret) {
556                 for (i=0; !ret && reload_classes[i].name; i++) {
557                         if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
558                                 ret = ast_strdup(reload_classes[i].name);
559                 }
560         }
561
562         return ret;
563 }
564
565 int ast_module_reload(const char *name)
566 {
567         struct ast_module *cur;
568         int res = 0; /* return value. 0 = not found, others, see below */
569         int i;
570
571         if (ast_mutex_trylock(&reloadlock)) {
572                 ast_verbose("The previous reload command didn't finish yet\n");
573                 return -1;      /* reload already in progress */
574         }
575         ast_lastreloadtime = ast_tvnow();
576
577         /* Call "predefined" reload here first */
578         for (i = 0; reload_classes[i].name; i++) {
579                 if (!name || !strcasecmp(name, reload_classes[i].name)) {
580                         reload_classes[i].reload_fn();  /* XXX should check error ? */
581                         res = 2;        /* found and reloaded */
582                 }
583         }
584
585         if (name && res) {
586                 ast_mutex_unlock(&reloadlock);
587                 return res;
588         }
589
590         AST_LIST_LOCK(&module_list);
591         AST_LIST_TRAVERSE(&module_list, cur, entry) {
592                 const struct ast_module_info *info = cur->info;
593
594                 if (name && resource_name_match(name, cur->resource))
595                         continue;
596
597                 if (!cur->flags.running || cur->flags.declined) {
598                         if (!name)
599                                 continue;
600                         ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
601                                 "Before reloading the module, you must run \"module load %s\" "
602                                 "and fix whatever is preventing the module from being initialized.\n",
603                                 name, name);
604                         res = 2; /* Don't report that the module was not found */
605                         break;
606                 }
607
608                 if (!info->reload) {    /* cannot be reloaded */
609                         if (res < 1)    /* store result if possible */
610                                 res = 1;        /* 1 = no reload() method */
611                         continue;
612                 }
613
614                 res = 2;
615                 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
616                 info->reload();
617         }
618         AST_LIST_UNLOCK(&module_list);
619
620         ast_mutex_unlock(&reloadlock);
621
622         return res;
623 }
624
625 static unsigned int inspect_module(const struct ast_module *mod)
626 {
627         if (!mod->info->description) {
628                 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
629                 return 1;
630         }
631
632         if (!mod->info->key) {
633                 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
634                 return 1;
635         }
636
637         if (verify_key((unsigned char *) mod->info->key)) {
638                 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
639                 return 1;
640         }
641
642         if (!ast_strlen_zero(mod->info->buildopt_sum) &&
643             strcmp(buildopt_sum, mod->info->buildopt_sum)) {
644                 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
645                 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
646                 return 1;
647         }
648
649         return 0;
650 }
651
652 static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only)
653 {
654         struct ast_module *mod;
655         enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
656         char tmp[256];
657
658         if ((mod = find_resource(resource_name, 0))) {
659                 if (mod->flags.running) {
660                         ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
661                         return AST_MODULE_LOAD_DECLINE;
662                 }
663                 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
664                         return AST_MODULE_LOAD_SKIP;
665         } else {
666 #ifdef LOADABLE_MODULES
667                 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
668                         /* don't generate a warning message during load_modules() */
669                         if (!global_symbols_only) {
670                                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
671                                 return AST_MODULE_LOAD_DECLINE;
672                         } else {
673                                 return AST_MODULE_LOAD_SKIP;
674                         }
675                 }
676 #else
677                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
678                 return AST_MODULE_LOAD_DECLINE;
679 #endif
680         }
681
682         if (inspect_module(mod)) {
683                 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
684 #ifdef LOADABLE_MODULES
685                 unload_dynamic_module(mod);
686 #endif
687                 return AST_MODULE_LOAD_DECLINE;
688         }
689
690         if (!mod->lib && mod->info->backup_globals()) {
691                 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
692                 return AST_MODULE_LOAD_DECLINE;
693         }
694
695         mod->flags.declined = 0;
696
697         if (mod->info->load)
698                 res = mod->info->load();
699
700         switch (res) {
701         case AST_MODULE_LOAD_SUCCESS:
702                 if (!ast_fully_booted) {
703                         ast_verb(1, "%s => (%s)\n", resource_name, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
704                         if (ast_opt_console && !option_verbose)
705                                 ast_verbose( ".");
706                 } else {
707                         ast_verb(1, "Loaded %s => (%s)\n", resource_name, mod->info->description);
708                 }
709
710                 mod->flags.running = 1;
711
712                 ast_update_use_count();
713                 break;
714         case AST_MODULE_LOAD_DECLINE:
715                 mod->flags.declined = 1;
716                 break;
717         case AST_MODULE_LOAD_FAILURE:
718                 break;
719         case AST_MODULE_LOAD_SKIP:
720                 /* modules should never return this value */
721                 break;
722         }
723
724         return res;
725 }
726
727 int ast_load_resource(const char *resource_name)
728 {
729         int res;
730         AST_LIST_LOCK(&module_list);
731         res = load_resource(resource_name, 0);
732         AST_LIST_UNLOCK(&module_list);
733
734         return res;
735 }
736
737 struct load_order_entry {
738         char *resource;
739         AST_LIST_ENTRY(load_order_entry) entry;
740 };
741
742 AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
743
744 static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order)
745 {
746         struct load_order_entry *order;
747
748         AST_LIST_TRAVERSE(load_order, order, entry) {
749                 if (!resource_name_match(order->resource, resource))
750                         return NULL;
751         }
752
753         if (!(order = ast_calloc(1, sizeof(*order))))
754                 return NULL;
755
756         order->resource = ast_strdup(resource);
757         AST_LIST_INSERT_TAIL(load_order, order, entry);
758
759         return order;
760 }
761 int load_modules(unsigned int preload_only)
762 {
763         struct ast_config *cfg;
764         struct ast_module *mod;
765         struct load_order_entry *order;
766         struct ast_variable *v;
767         unsigned int load_count;
768         struct load_order load_order;
769         int res = 0;
770         struct ast_flags config_flags = { 0 };
771         int modulecount = 0;
772 #ifdef LOADABLE_MODULES
773         struct dirent *dirent;
774         DIR *dir;
775 #endif
776
777         /* all embedded modules have registered themselves by now */
778         embedding = 0;
779
780         ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
781
782         AST_LIST_HEAD_INIT_NOLOCK(&load_order);
783
784         AST_LIST_LOCK(&module_list);
785
786         if (embedded_module_list.first) {
787                 module_list.first = embedded_module_list.first;
788                 module_list.last = embedded_module_list.last;
789                 embedded_module_list.first = NULL;
790         }
791
792         if (!(cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags))) {
793                 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
794                 goto done;
795         }
796
797         /* first, find all the modules we have been explicitly requested to load */
798         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
799                 if (!strcasecmp(v->name, preload_only ? "preload" : "load"))
800                         add_to_load_order(v->value, &load_order);
801         }
802
803         /* check if 'autoload' is on */
804         if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
805                 /* if so, first add all the embedded modules that are not already running to the load order */
806                 AST_LIST_TRAVERSE(&module_list, mod, entry) {
807                         /* if it's not embedded, skip it */
808                         if (mod->lib)
809                                 continue;
810
811                         if (mod->flags.running)
812                                 continue;
813
814                         order = add_to_load_order(mod->resource, &load_order);
815                 }
816
817 #ifdef LOADABLE_MODULES
818                 /* if we are allowed to load dynamic modules, scan the directory for
819                    for all available modules and add them as well */
820                 if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
821                         while ((dirent = readdir(dir))) {
822                                 int ld = strlen(dirent->d_name);
823
824                                 /* Must end in .so to load it.  */
825
826                                 if (ld < 4)
827                                         continue;
828
829                                 if (strcasecmp(dirent->d_name + ld - 3, ".so"))
830                                         continue;
831
832                                 /* if there is already a module by this name in the module_list,
833                                    skip this file */
834                                 if (find_resource(dirent->d_name, 0))
835                                         continue;
836
837                                 add_to_load_order(dirent->d_name, &load_order);
838                         }
839
840                         closedir(dir);
841                 } else {
842                         if (!ast_opt_quiet)
843                                 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
844                                         ast_config_AST_MODULE_DIR);
845                 }
846 #endif
847         }
848
849         /* now scan the config for any modules we are prohibited from loading and
850            remove them from the load order */
851         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
852                 if (strcasecmp(v->name, "noload"))
853                         continue;
854
855                 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
856                         if (!resource_name_match(order->resource, v->value)) {
857                                 AST_LIST_REMOVE_CURRENT(entry);
858                                 ast_free(order->resource);
859                                 ast_free(order);
860                         }
861                 }
862                 AST_LIST_TRAVERSE_SAFE_END;
863         }
864
865         /* we are done with the config now, all the information we need is in the
866            load_order list */
867         ast_config_destroy(cfg);
868
869         load_count = 0;
870         AST_LIST_TRAVERSE(&load_order, order, entry)
871                 load_count++;
872
873         if (load_count)
874                 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
875
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                         modulecount++;
881                 case AST_MODULE_LOAD_DECLINE:
882                         AST_LIST_REMOVE_CURRENT(entry);
883                         ast_free(order->resource);
884                         ast_free(order);
885                         break;
886                 case AST_MODULE_LOAD_FAILURE:
887                         res = -1;
888                         goto done;
889                 case AST_MODULE_LOAD_SKIP:
890                         /* try again later */
891                         break;
892                 }
893         }
894         AST_LIST_TRAVERSE_SAFE_END;
895
896         /* now load everything else */
897         AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
898                 switch (load_resource(order->resource, 0)) {
899                 case AST_MODULE_LOAD_SUCCESS:
900                         modulecount++;
901                 case AST_MODULE_LOAD_DECLINE:
902                         AST_LIST_REMOVE_CURRENT(entry);
903                         ast_free(order->resource);
904                         ast_free(order);
905                         break;
906                 case AST_MODULE_LOAD_FAILURE:
907                         res = -1;
908                         goto done;
909                 case AST_MODULE_LOAD_SKIP:
910                         /* should not happen */
911                         break;
912                 }
913         }
914         AST_LIST_TRAVERSE_SAFE_END;
915
916 done:
917         while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
918                 ast_free(order->resource);
919                 ast_free(order);
920         }
921
922         AST_LIST_UNLOCK(&module_list);
923         
924         /* Tell manager clients that are aggressive at logging in that we're done
925            loading modules. If there's a DNS problem in chan_sip, we might not
926            even reach this */
927         manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
928         
929         return res;
930 }
931
932 void ast_update_use_count(void)
933 {
934         /* Notify any module monitors that the use count for a
935            resource has changed */
936         struct loadupdate *m;
937
938         AST_LIST_LOCK(&updaters);
939         AST_LIST_TRAVERSE(&updaters, m, entry)
940                 m->updater();
941         AST_LIST_UNLOCK(&updaters);
942 }
943
944 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
945                            const char *like)
946 {
947         struct ast_module *cur;
948         int unlock = -1;
949         int total_mod_loaded = 0;
950
951         if (AST_LIST_TRYLOCK(&module_list))
952                 unlock = 0;
953  
954         AST_LIST_TRAVERSE(&module_list, cur, entry) {
955                 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
956         }
957
958         if (unlock)
959                 AST_LIST_UNLOCK(&module_list);
960
961         return total_mod_loaded;
962 }
963
964 /*! \brief Check if module exists */
965 int ast_module_check(const char *name)
966 {
967         struct ast_module *cur;
968
969         if (ast_strlen_zero(name))
970                 return 0;       /* FALSE */
971
972         cur = find_resource(name, 1);
973
974         return (cur != NULL);
975 }
976
977
978 int ast_loader_register(int (*v)(void))
979 {
980         struct loadupdate *tmp;
981
982         if (!(tmp = ast_malloc(sizeof(*tmp))))
983                 return -1;
984
985         tmp->updater = v;
986         AST_LIST_LOCK(&updaters);
987         AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
988         AST_LIST_UNLOCK(&updaters);
989
990         return 0;
991 }
992
993 int ast_loader_unregister(int (*v)(void))
994 {
995         struct loadupdate *cur;
996
997         AST_LIST_LOCK(&updaters);
998         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
999                 if (cur->updater == v)  {
1000                         AST_LIST_REMOVE_CURRENT(entry);
1001                         break;
1002                 }
1003         }
1004         AST_LIST_TRAVERSE_SAFE_END;
1005         AST_LIST_UNLOCK(&updaters);
1006
1007         return cur ? 0 : -1;
1008 }
1009
1010 struct ast_module *ast_module_ref(struct ast_module *mod)
1011 {
1012         ast_atomic_fetchadd_int(&mod->usecount, +1);
1013         ast_update_use_count();
1014
1015         return mod;
1016 }
1017
1018 void ast_module_unref(struct ast_module *mod)
1019 {
1020         ast_atomic_fetchadd_int(&mod->usecount, -1);
1021         ast_update_use_count();
1022 }