remove an unused function
[asterisk/asterisk.git] / loader.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Module Loader
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  * - See ModMngMnt
25  */
26
27 #include <stdio.h>
28 #include <dirent.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include "asterisk/linkedlists.h"
38 #include "asterisk/module.h"
39 #include "asterisk/options.h"
40 #include "asterisk/config.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/term.h"
44 #include "asterisk/manager.h"
45 #include "asterisk/cdr.h"
46 #include "asterisk/enum.h"
47 #include "asterisk/rtp.h"
48 #include "asterisk/http.h"
49 #include "asterisk/lock.h"
50 #ifdef DLFCNCOMPAT
51 #include "asterisk/dlfcn-compat.h"
52 #else
53 #include <dlfcn.h>
54 #endif
55 #include "asterisk/md5.h"
56 #include "asterisk/utils.h"
57
58 #ifndef RTLD_NOW
59 #define RTLD_NOW 0
60 #endif
61
62 static int modlistver = 0; /* increase whenever the list changes, to protect reload */
63
64 static unsigned char expected_key[] =
65 { 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
66   0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 };
67
68 /*
69  * Modules can be in a number of different states, as below:
70  * MS_FAILED    attempt to load failed. This is final.
71  * MS_NEW       just added to the list, symbols unresolved.
72  * MS_RESOLVED  all symbols resolved, but supplier modules not active yet.
73  * MS_CANLOAD   all symbols resolved and suppliers are all active
74  *              (or we are in a cyclic dependency and we are breaking a loop)
75  * MS_ACTIVE    load() returned successfully.
76  */
77 enum st_t {  /* possible states of a module */
78         MS_FAILED = 0,              /*!< cannot load */
79         MS_NEW = 1,                 /*!< nothing known */
80         MS_RESOLVED = 2,            /*!< all required resolved */
81         MS_CANLOAD = 3,             /*!< as above, plus cyclic depend.*/
82         MS_ACTIVE = 4,              /*!< all done */
83 };
84
85 /*! \note
86  * All module symbols are in module_symbols.
87  * Modules are then linked in a list of struct module,
88  * whereas updaters are in a list of struct loadupdate.
89  *
90  * Both lists (basically, the entire loader) are protected by
91  * the lock in module_list.
92  *
93  * A second lock, reloadlock, is used to prevent concurrent reloads
94  */
95 struct module {
96         AST_LIST_ENTRY(module) next;
97         struct module_symbols cb;
98         void *lib;              /* the shared lib */
99         char resource[256];
100
101         enum st_t state;
102         int export_refcount;    /* how many users of exported symbols */
103 };
104
105 struct loadupdate {
106         AST_LIST_ENTRY(loadupdate) next;
107         int (*updater)(void);
108 };
109
110 static AST_LIST_HEAD_STATIC(module_list, module);
111 static AST_LIST_HEAD_STATIC(updaters, loadupdate);
112 AST_MUTEX_DEFINE_STATIC(reloadlock);
113
114 /*! \note
115  * helper localuser routines.
116  * All of these routines are extremely expensive, so the use of
117  * macros is totally unnecessary from the point of view of performance:
118  * the extra function call will be totally negligible in all cases.
119  */
120
121 struct localuser *ast_localuser_add(struct ast_module_lock *m,
122         struct ast_channel *chan)
123 {
124         struct localuser *u = ast_calloc(1, sizeof(*u));
125         if (u == NULL)
126                 return NULL;
127         u->chan = chan;
128         ast_mutex_lock(&m->lock);
129         AST_LIST_INSERT_HEAD(&m->u, u, next);
130         m->usecnt++;
131         ast_mutex_unlock(&m->lock);
132         ast_update_use_count();
133         return u;
134 }
135
136 void ast_localuser_remove(struct ast_module_lock *m, struct localuser *u)
137 {
138         ast_mutex_lock(&m->lock);
139         AST_LIST_REMOVE(&m->u, u, next);
140         m->usecnt--;
141         free(u);
142         ast_mutex_unlock(&m->lock);
143         ast_update_use_count();
144 }
145
146 void ast_hangup_localusers(struct ast_module_lock *m)
147 {
148         struct localuser *u;
149         ast_mutex_lock(&m->lock);
150         AST_LIST_TRAVERSE_SAFE_BEGIN(&m->u, u, next) {
151                 ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
152                 free(u);
153                 AST_LIST_REMOVE_CURRENT(&m->u, next);
154         }
155         AST_LIST_TRAVERSE_SAFE_END
156         m->usecnt = 0;
157         ast_mutex_unlock(&m->lock);
158         ast_update_use_count();
159 }
160
161 /*--- new-style loader routines ---*/
162
163 /*
164  * For backward compatibility, we have 3 types of loadable modules:
165  *
166  * MOD_0 these are the 'old style' modules, which export a number
167  *       of callbacks, and their full interface, as globally visible
168  *       symbols. The module needs to be loaded with RTLD_LAZY and
169  *       RTLD_GLOBAL to make symbols visible to other modules, and
170  *       to avoid load failures due to cross dependencies.
171  *
172  * MOD_1 almost as above, but the generic callbacks are all into a
173  *       a structure, mod_data. Same load requirements as above.
174  *
175  * MOD_2 this is the 'new style' format for modules. The module must
176  *       explictly declare which simbols are exported and which
177  *       symbols from other modules are used, and the code in this
178  *       loader will implement appropriate checks to load the modules
179  *       in the correct order. Also this allows to load modules
180  *       with RTLD_NOW and RTLD_LOCAL so there is no chance of run-time
181  *       bugs due to unresolved symbols or name conflicts.
182  */
183
184 /*
185  * helper routine to print the symbolic name associated to a state
186  */
187 static const char *st_name(enum st_t state)
188 {
189         /* try to resolve required symbols */
190         const char *st;
191         switch (state) {
192 #define ST(x)  case x: st = # x; break;
193         ST(MS_NEW);
194         ST(MS_FAILED);
195         ST(MS_RESOLVED);
196         ST(MS_ACTIVE);
197         ST(MS_CANLOAD);
198         default:
199                 st = "unknown";
200         }
201         return st;
202 #undef ST
203 }
204
205 /*! \brief
206  * Fetch/release an exported symbol - modify export_refcount by delta
207  * \param delta 1 to fetch a symbol, -1 to release it.
208  * \return on success, return symbol value.
209  * \note Note, modules in MS_FAIL will never match in a 'get' request.
210  * If src is non-NULL, on exit *src points to the source module.
211  *
212  * Must be called with the lock held.
213  */
214 static void *module_symbol_helper(const char *name,
215                 int delta, struct module **src)
216 {
217         void *ret = NULL;
218         struct module *m;
219
220         AST_LIST_TRAVERSE(&module_list, m, next) {
221                 struct symbol_entry *es;
222                 if (delta > 0 && m->state == MS_FAILED)
223                         continue; /* cannot 'get' a symbol from a failed module */
224                 for (es = m->cb.exported_symbols; ret == NULL && es && es->name; es++) {
225                         if (!strcmp(es->name, name)) {
226                                 ret = es->value;
227                                 m->export_refcount += delta;
228                                 if (src)
229                                         *src = m;
230                                 break;
231                         }
232                 }
233                 if (ret)
234                         break;
235         }
236         if (ret == NULL)
237                 ast_log(LOG_WARNING, "symbol %s not found\n", name);
238         return ret;
239 }
240
241 static void *release_module_symbol(const char *name)
242 {
243         return module_symbol_helper(name, -1, NULL);
244 }
245
246 static void *get_module_symbol(const char *name, struct module **src)
247 {
248         return module_symbol_helper(name, +1, src);
249 }
250
251 /*!
252  * \brief Release refcounts to all imported symbols,
253  * and change module state to MS_FAILED.
254  */
255 static void release_module(struct module *m)
256 {
257         struct symbol_entry *s;
258
259         for (s = m->cb.required_symbols; s && s->name != NULL; s++) {
260                 if (s->value != NULL) {
261                         release_module_symbol(s->name);
262                         s->value = NULL;
263                 }
264         }
265         m->state = MS_FAILED;
266 }
267
268 /*! \brief check that no NULL symbols are exported  - the algorithms rely on that. */
269 static int check_exported(struct module *m)
270 {
271         struct symbol_entry *es = m->cb.exported_symbols;
272         int errors = 0;
273
274         if (es == NULL)
275                 return 0;
276         ast_log(LOG_WARNING, "module %s exports the following symbols\n",
277                 es->name);
278         for (; es->name; es++) {
279                 void **p = es->value;
280                 int i;
281
282                 ast_log(LOG_WARNING, "\taddr %p size %8d %s\n",
283                         es->value, es->size, es->name);
284                 for (i = 0; i <  es->size / sizeof(void *); i++, p++) {
285                         if (*p == NULL) {
286                                 ast_log(LOG_WARNING, "\t *** null field at offset %d\n", i);
287                                         errors++;
288                         }
289                 }
290         }
291         return errors;
292 }
293
294 /*!
295  * \brief Resolve symbols and change state accordingly.
296  * \return Return 1 if state changed, 0 otherwise.
297  * \note If MS_FAILED, MS_ACTIVE or MS_CANLOAD there is nothing to do.
298  * If a symbol cannot be resolved (no supplier or supplier in MS_FAIL),
299  * move to MS_FAIL and release all symbols;
300  * If all suppliers are MS_ACTIVE, move to MS_CANLOAD
301  * otherwise move to MS_RESOLVED.
302  */
303 static int resolve(struct module *m)
304 {
305         struct symbol_entry *s;
306
307         if (m->state == MS_FAILED || m->state == MS_ACTIVE || m->state == MS_CANLOAD)
308                 return 0;       /* already decided what to do */
309         /* now it's either MS_NEW or MS_RESOLVED.
310          * Be optimistic and put it in MS_CANLOAD, then try to
311          * resolve and verify symbols, and downgrade as appropriate.
312          */
313         m->state = MS_CANLOAD;
314         for (s = m->cb.required_symbols; s && s->name != NULL; s++) {
315                 void **p = (void **)(s->value);
316
317                 if (*p == NULL)         /* symbol not resolved yet */
318                         *p = get_module_symbol(s->name, &s->src);
319                 if (*p == NULL || s->src->state == MS_FAILED) {        /* fail */
320                         ast_log(LOG_WARNING,
321                                 "Unresolved symbol %s for module %s\n",
322                                 s->name, m->resource);
323                         release_module(m); /* and set to MS_FAILED */
324                         break;
325                 }
326                 if (s->src->state != MS_ACTIVE)
327                         m->state = MS_RESOLVED; /* downgrade */
328         }
329         return 1;
330 }
331
332 /*!
333  * \brief Fixup references and load modules according to their dependency order.
334  * Called when new modules are added to the list.
335  * The algorithm is as follows:
336  * - all modules MS_FAILED are changed to MS_NEW, in case something
337  *      happened that could help them.
338  * - first try to resolve symbols. If successful, change the
339  *   module's state to MS_RESOLVED otherwise to MS_FAILED
340  * - repeat on all modules until there is progress:
341  *    - if it is MS_ACTIVE or MS_FAILED, continue (no progress)
342  *    - if one has all required modules in MS_ACTIVE, try to load it.
343  *      If successful it becomes MS_ACTIVE itself, otherwise
344  *             MS_FAILED and releases all symbols.
345  *             In any case, we have progress.
346  *    - if one of the dependencies is MS_FAILED, release and set to
347  *      MS_FAILED here too. We have progress.
348  * - if we have no progress there is a cyclic dependency.
349  *      Take first and change to MS_CANLOAD, i.e. as if all required are
350  *      MS_ACTIVE. we have progress, so repeat.
351  * \par NOTE:
352  *   - must be called with lock held
353  *   - recursive calls simply return success.
354  */
355 static int fixup(const char *caller)
356 {
357         struct module *m;
358         int total = 0, new = 0, cycle = 0;
359         static int in_fixup = 0;        /* disable recursive calls */
360
361         if (in_fixup)
362                 return 0;
363         in_fixup++;
364         AST_LIST_TRAVERSE(&module_list, m, next) {
365                 total++;
366                 if (m->state == MS_FAILED)
367                         m->state = MS_NEW;
368                 if (m->state == MS_NEW)
369                         new++;
370                 /* print some debugging info for new modules */
371                 if (m->state == MS_NEW &&
372                     (m->cb.exported_symbols || m->cb.required_symbols))
373                         ast_log(LOG_NOTICE,
374                             "module %-30s exports %p requires %p state %s(%d)\n",
375                                 m->resource, m->cb.exported_symbols,
376                                 m->cb.required_symbols,
377                                 st_name(m->state), m->state);
378         }
379         ast_log(LOG_DEBUG, "---- fixup (%s): %d modules, %d new ---\n",
380                 caller, total, new);
381         for (;;cycle++) {
382                 int again = 0;  /* set if we need another round */
383                 
384                 ast_log(LOG_DEBUG, "---- fixup: cycle %d ---\n", cycle);
385                 AST_LIST_TRAVERSE(&module_list, m, next) {
386                         if (resolve(m))
387                                 again = 1;      /* something changed */
388                         if (m->state != MS_CANLOAD)     /* for now, done with this module */
389                                 continue;
390                         /* try to run the load routine */
391                         if (m->cb.load_module()) { /* error */
392                                 ast_log(LOG_WARNING, "load_module %s fail\n",
393                                         m->resource);
394                                 release_module(m); /* and set to MS_FAIL */
395                         } else {
396                                 ast_log(LOG_WARNING, "load_module %s success\n",
397                                         m->resource);
398                                 m->state = MS_ACTIVE;
399                         }
400                         again = 1;      /* something has changed */
401                 }
402                 /* Modules in MS_RESOLVED mean a possible cyclic dependency.
403                  * Break the indecision by setting one to CANLOAD, and repeat.
404                  */
405                 AST_LIST_TRAVERSE(&module_list, m, next) {
406                         if (m->state == MS_RESOLVED) {
407                                 m->state = MS_CANLOAD;
408                                 again = 1;
409                                 break;
410                         }
411                 }
412                 if (!again)     /* we are done */
413                         break;
414         }
415         ast_log(LOG_DEBUG, "---- fixup complete ---\n");
416         in_fixup--;
417         return 0;
418 }
419
420 /* test routines to see which modules depend on global symbols
421  * exported by other modules.
422  */
423 static void check_symbols(void)
424 {
425         struct dirent *d;
426         DIR *mods = opendir(ast_config_AST_MODULE_DIR);
427         void *lib;
428         char buf[1024];
429
430         ast_log(LOG_WARNING, "module dir <%s>\n", ast_config_AST_MODULE_DIR);
431         if (!mods)
432                 return;
433         while((d = readdir(mods))) {
434                 int ld = strlen(d->d_name);
435                 /* Must end in .so to load it.  */
436                 if (ld <= 3 || strcasecmp(d->d_name + ld - 3, ".so"))
437                         continue;
438                 snprintf(buf, sizeof(buf), "%s/%s", ast_config_AST_MODULE_DIR, d->d_name);
439                 lib = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
440                 if (lib == NULL) {
441                         ast_log(LOG_WARNING, "(notice only) module %s error %s\n", d->d_name, dlerror());
442                 }
443                 dlclose(lib);
444         }
445 }
446 /*--- end new-style routines ---*/
447
448 /*! \note
449  * In addition to modules, the reload command handles some extra keywords
450  * which are listed here together with the corresponding handlers.
451  * This table is also used by the command completion code.
452  */
453 static struct reload_classes_t {
454         const char *name;
455         int (*reload_fn)(void);
456 } reload_classes[] = {  /* list in alpha order, longest match first */
457         { "cdr",        ast_cdr_engine_reload },
458         { "dnsmgr",     dnsmgr_reload },
459         { "extconfig",  read_config_maps },
460         { "enum",       ast_enum_reload },
461         { "manager",    reload_manager },
462         { "rtp",        ast_rtp_reload },
463         { "http",       ast_http_reload },
464         { NULL, NULL }
465 };
466
467 static int printdigest(const unsigned char *d)
468 {
469         int x, pos;
470         char buf[256]; /* large enough so we don't have to worry */
471
472         for (pos = 0, x=0; x<16; x++)
473                 pos += sprintf(buf + pos, " %02x", *d++);
474         ast_log(LOG_DEBUG, "Unexpected signature:%s\n", buf);
475         return 0;
476 }
477
478 static int key_matches(const unsigned char *key1, const unsigned char *key2)
479 {
480         int x;
481         for (x=0; x<16; x++) {
482                 if (key1[x] != key2[x]) /* mismatch - fail now. */
483                         return 0;
484         }
485         return 1;
486 }
487
488 static int verify_key(const unsigned char *key)
489 {
490         struct MD5Context c;
491         unsigned char digest[16];
492         MD5Init(&c);
493         MD5Update(&c, key, strlen((char *)key));
494         MD5Final(digest, &c);
495         if (key_matches(expected_key, digest))
496                 return 0;
497         printdigest(digest);
498         return -1;
499 }
500
501 int ast_unload_resource(const char *resource_name, int force)
502 {
503         struct module *cur;
504         int res = -1;
505         int error = 0;
506         if (AST_LIST_LOCK(&module_list)) /* XXX should fail here ? */
507                 ast_log(LOG_WARNING, "Failed to lock\n");
508         AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, cur, next) {
509                 struct module_symbols *m = &cur->cb;
510                 
511                 if (strcasecmp(cur->resource, resource_name))   /* not us */
512                         continue;
513                 if ((res = m->usecount()) > 0)  {
514                         if (force) 
515                                 ast_log(LOG_WARNING, "Warning:  Forcing removal of module %s with use count %d\n", resource_name, res);
516                         else {
517                                 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, res);
518                                 error = 1;
519                                 break;
520                         }
521                 }
522                 res = m->unload_module();
523                 if (res) {
524                         ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
525                         if (force <= AST_FORCE_FIRM) {
526                                 error = 1;
527                                 break;
528                         } else
529                                 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
530                 }
531                 release_module(cur);    /* XXX */
532                 AST_LIST_REMOVE_CURRENT(&module_list, next);
533                 dlclose(cur->lib);
534                 free(cur);
535                 break;
536         }
537         AST_LIST_TRAVERSE_SAFE_END;
538         if (!error)
539                 modlistver++;
540         AST_LIST_UNLOCK(&module_list);
541         if (!error)     /* XXX maybe within the lock ? */
542                 ast_update_use_count();
543         return res;
544 }
545
546 char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
547 {
548         struct module *cur;
549         int i, which=0, l = strlen(word);
550         char *ret = NULL;
551
552         if (pos != rpos)
553                 return NULL;
554         AST_LIST_LOCK(&module_list);
555         AST_LIST_TRAVERSE(&module_list, cur, next) {
556                 if (!strncasecmp(word, cur->resource, l) && (cur->cb.reload || !needsreload) &&
557                                 ++which > state) {
558                         ret = strdup(cur->resource);
559                         break;
560                 }
561         }
562         AST_LIST_UNLOCK(&module_list);
563         if (!ret) {
564                 for (i=0; !ret && reload_classes[i].name; i++) {
565                         if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
566                                 ret = strdup(reload_classes[i].name);
567                 }
568         }
569         return ret;
570 }
571
572 int ast_module_reload(const char *name)
573 {
574         struct module *cur;
575         int res = 0; /* return value. 0 = not found, others, see below */
576         int i, oldversion;
577         int (*reload)(void);
578
579         if (ast_mutex_trylock(&reloadlock)) {
580                 ast_verbose("The previous reload command didn't finish yet\n");
581                 return -1;      /* reload already in progress */
582         }
583         /* Call "predefined" reload here first */
584         for (i = 0; reload_classes[i].name; i++) {
585                 if (!name || !strcasecmp(name, reload_classes[i].name)) {
586                         reload_classes[i].reload_fn();  /* XXX should check error ? */
587                         res = 2;        /* found and reloaded */
588                 }
589         }
590         ast_lastreloadtime = time(NULL);
591
592         AST_LIST_LOCK(&module_list);
593         oldversion = modlistver;
594         AST_LIST_TRAVERSE(&module_list, cur, next) {
595                 struct module_symbols *m = &cur->cb;
596                 if (name && strcasecmp(name, cur->resource))    /* not ours */
597                         continue;
598                 reload = m->reload;
599                 if (!reload) {  /* cannot be reloaded */
600                         if (res < 1)    /* store result if possible */
601                                 res = 1;        /* 1 = no reload() method */
602                         continue;
603                 }
604                 /* drop the lock and try a reload. if successful, break */
605                 AST_LIST_UNLOCK(&module_list);
606                 res = 2;
607                 if (option_verbose > 2) 
608                         ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", cur->resource, m->description());
609                 reload();
610                 AST_LIST_LOCK(&module_list);
611                 if (oldversion != modlistver) /* something changed, abort */
612                         break;
613         }
614         AST_LIST_UNLOCK(&module_list);
615         ast_mutex_unlock(&reloadlock);
616         return res;
617 }
618
619 static int resource_exists(const char *resource, int do_lock)
620 {
621         struct module *cur;
622         if (do_lock && AST_LIST_LOCK(&module_list))
623                 ast_log(LOG_WARNING, "Failed to lock\n");
624         AST_LIST_TRAVERSE(&module_list, cur, next) {
625                 if (!strcasecmp(resource, cur->resource))
626                         break;
627         }
628         if (do_lock)
629                 AST_LIST_UNLOCK(&module_list);
630         return cur ? -1 : 0;
631 }
632
633 /* lookup a symbol with or without leading '_', accept either form in input */
634 static void *find_symbol(struct module *m, const char *name, int verbose)
635 {
636         char *n1;
637         void *s;
638
639         if (name[0] == '_')
640                 name++;
641         if (!(n1 = alloca(strlen(name) + 2))) /* room for leading '_' and final '\0' */
642                 return NULL;
643         n1[0] = '_';
644         strcpy(n1+1, name);
645         s = dlsym(m->lib, n1+1);        /* try without '_' */
646         if (s == NULL)
647                 s = dlsym(m->lib, n1);
648         if (verbose && s == NULL)
649                 ast_log(LOG_WARNING, "No symbol '%s' in module '%s\n",
650                         n1, m->resource);
651         return s;
652 }
653
654 /* XXX cfg is only used for !res_* and #ifdef RTLD_GLOBAL */
655 static struct module * __load_resource(const char *resource_name,
656         const struct ast_config *cfg)
657 {
658         static char fn[256];
659         int errors=0;
660         int res;
661         struct module *cur;
662         struct module_symbols *m, *m1;
663         int flags = RTLD_NOW;
664         unsigned char *key;
665         char tmp[80];
666
667 #ifndef RTLD_GLOBAL
668 #define RTLD_GLOBAL     0       /* so it is a No-op */
669 #endif
670         if (strncasecmp(resource_name, "res_", 4) && cfg) {
671                 char *val = ast_variable_retrieve(cfg, "global", resource_name);
672                 if (val && ast_true(val))
673                         flags |= RTLD_GLOBAL;
674         } else {
675                 /* Resource modules are always loaded global and lazy */
676                 flags = (RTLD_GLOBAL | RTLD_LAZY);
677         }
678         
679         if (AST_LIST_LOCK(&module_list))
680                 ast_log(LOG_WARNING, "Failed to lock\n");
681         if (resource_exists(resource_name, 0)) {
682                 ast_log(LOG_WARNING, "Module '%s' already exists\n", resource_name);
683                 AST_LIST_UNLOCK(&module_list);
684                 return NULL;
685         }
686         if (!(cur = ast_calloc(1, sizeof(*cur)))) {
687                 AST_LIST_UNLOCK(&module_list);
688                 return NULL;
689         }
690         m = &cur->cb;
691         ast_copy_string(cur->resource, resource_name, sizeof(cur->resource));
692         if (resource_name[0] == '/')
693                 ast_copy_string(fn, resource_name, sizeof(fn));
694         else
695                 snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_MODULE_DIR, resource_name);
696
697         /* open in a sane way */
698         cur->lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
699         if (cur->lib == NULL) {
700                 ast_log(LOG_WARNING, "cannot load %s %s\n", fn, dlerror());
701         } else if ( (m1 = find_symbol(cur, "mod_data", 0)) == NULL || m1->type == MOD_0) {
702                 /* old-style module, close and reload with standard flags */
703                 dlclose(cur->lib);
704                 cur->lib = NULL;
705         }
706         if (cur->lib == NULL)   /* try reopen with the old style */
707                 cur->lib = dlopen(fn, flags);
708
709         if (!cur->lib) {
710                 ast_log(LOG_WARNING, "%s\n", dlerror());
711                 free(cur);
712                 AST_LIST_UNLOCK(&module_list);
713                 return NULL;
714         }
715         m1 = find_symbol(cur, "mod_data", 0);
716         if (m1 != NULL) {       /* new style module */
717                 ast_log(LOG_WARNING, "new style %s (%d) loaded RTLD_LOCAL\n",
718                         resource_name, m1->type);
719                 errors = check_exported(cur);
720                 *m = *m1;
721         } else {
722                 m->type = MOD_0;
723                 m->load_module = find_symbol(cur, "load_module", 1);
724                 m->unload_module = find_symbol(cur, "unload_module", 1);
725                 m->usecount = find_symbol(cur, "usecount", 1);
726                 m->description = find_symbol(cur, "description", 1);
727                 m->key = find_symbol(cur, "key", 1);
728                 m->reload = find_symbol(cur, "reload", 0);
729         }
730         if (!m->load_module)
731                 errors++;
732         if (!m->unload_module)
733                 errors++;
734         if (!m->usecount)
735                 errors++;
736         if (!m->description)
737                 errors++;
738         if (!m->key)
739                 errors++;
740         if (!m->key || !(key = (unsigned char *) m->key())) {
741                 ast_log(LOG_WARNING, "Key routine returned NULL in module %s\n", fn);
742                 key = NULL;
743                 errors++;
744         }
745         if (key && verify_key(key)) {
746                 ast_log(LOG_WARNING, "Unexpected key returned by module %s\n", fn);
747                 errors++;
748         }
749         if (errors) {
750                 ast_log(LOG_WARNING, "%d error%s loading module %s, aborted\n", errors, (errors != 1) ? "s" : "", fn);
751                 dlclose(cur->lib);
752                 free(cur);
753                 AST_LIST_UNLOCK(&module_list);
754                 return NULL;
755         }
756         if (!ast_fully_booted) {
757                 if (option_verbose) 
758                         ast_verbose( " => (%s)\n", term_color(tmp, m->description(), COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
759                 if (ast_opt_console && !option_verbose)
760                         ast_verbose( ".");
761         } else {
762                 if (option_verbose)
763                         ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", fn, m->description());
764         }
765
766         AST_LIST_INSERT_TAIL(&module_list, cur, next);
767         /* add module to end of module_list chain
768            so reload commands will be issued in same order modules were loaded */
769         
770         modlistver++;
771         if (m->type == MOD_2) {
772                 ast_log(LOG_WARNING, "new-style module %s, deferring load()\n",
773                         resource_name);
774                 cur->state = MS_NEW;
775         } else
776                 cur->state = MS_CANLOAD;
777         /* XXX make sure the usecount is 1 before releasing the lock */
778         AST_LIST_UNLOCK(&module_list);
779         
780         if (cur->state == MS_CANLOAD && (res = m->load_module())) {
781                 ast_log(LOG_WARNING, "%s: load_module failed, returning %d\n", resource_name, res);
782                 ast_unload_resource(resource_name, 0);
783                 return NULL;
784         }
785         cur->state = MS_ACTIVE;
786         ast_update_use_count();
787         return cur;
788 }
789
790 /*!
791  * \brief load a single module (API call).
792  * (recursive calls from load_module() succeed.
793  * \return Returns 0 on success, -1 on error.
794  */
795 int ast_load_resource(const char *resource_name)
796 {
797         int o = option_verbose;
798         struct ast_config *cfg = NULL;
799         struct module *m;
800
801         option_verbose = 0;     /* Keep the module file parsing silent */
802         cfg = ast_config_load(AST_MODULE_CONFIG);
803         option_verbose = o;     /* restore verbosity */
804         m = __load_resource(resource_name, cfg);
805         if (cfg)
806                 ast_config_destroy(cfg);
807         return m ? 0 : -1;
808 }       
809
810 #if 0
811 +/*
812 + * load a single module (API call).
813 + * (recursive calls from load_module() succeed.
814 + */
815 +int ast_load_resource(const char *resource_name)
816 +{
817 +       struct module *m;
818 +       int ret;
819 +
820 +       ast_mutex_lock(&modlock);
821 +       m = __load_resource(resource_name, 0);
822 +       fixup(resource_name);
823 +       ret = (m->state == MS_FAILED) ? -1 : 0;
824 +       ast_mutex_unlock(&modlock);
825 +       return ret;
826 +}
827 #endif
828
829 /*! \brief if enabled, log and output on console the module's name, and try load it */
830 static int print_and_load(const char *s, struct ast_config *cfg)
831 {
832         char tmp[80];
833
834         if (option_debug && !option_verbose)
835                 ast_log(LOG_DEBUG, "Loading module %s\n", s);
836         if (option_verbose) {
837                 ast_verbose(VERBOSE_PREFIX_1 "[%s]",
838                         term_color(tmp, s, COLOR_BRWHITE, 0, sizeof(tmp)));
839                 fflush(stdout);
840         }
841         if (__load_resource(s, cfg))
842                 return 0; /* success */
843         ast_log(LOG_WARNING, "Loading module %s failed!\n", s);
844         return -1;
845 }
846
847 static const char *loadorder[] =
848 {
849         "res_",
850         "pbx_",
851         "chan_",
852         NULL,
853 };
854
855 int load_modules(const int preload_only)
856 {
857         struct ast_config *cfg;
858         int x;
859
860         if (option_verbose) {
861                 ast_verbose(preload_only ?
862                         "Asterisk Dynamic Loader loading preload modules:\n" :
863                         "Asterisk Dynamic Loader Starting:\n");
864         }
865
866         if (0)
867                 check_symbols();
868
869         cfg = ast_config_load(AST_MODULE_CONFIG);
870
871         if (cfg) {
872                 const char *cmd = preload_only ? "preload" : "load";
873                 struct ast_variable *v;
874                 /* Load explicitly defined modules */
875                 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
876                         if (strcasecmp(v->name, cmd)) /* not what we are looking for */
877                                 continue;
878                         if (print_and_load(v->value, cfg)) {    /* XXX really fatal ? */
879                                 ast_config_destroy(cfg);
880                                 return -1;
881                         }
882                 }
883         }
884
885         if (preload_only)
886                 goto done;
887
888         if (cfg && !ast_true(ast_variable_retrieve(cfg, "modules", "autoload")))
889                 /* no autoload */
890                 goto done;
891         /*
892          * Load all modules. To help resolving dependencies, we load modules
893          * in the order defined by loadorder[], with the final step for
894          * all modules with other prefixes.
895          * (XXX the new loader does not need this).
896          */
897
898         for (x=0; x<sizeof(loadorder) / sizeof(loadorder[0]); x++) {
899                 struct dirent *d;
900                 DIR *mods = opendir(ast_config_AST_MODULE_DIR);
901                 const char *base = loadorder[x];
902                 int lx = base ? strlen(base) : 0;
903
904                 if (!mods) {
905                         if (!ast_opt_quiet)
906                                 ast_log(LOG_WARNING, "Unable to open modules directory %s.\n",
907                                         ast_config_AST_MODULE_DIR);
908                         break; /* suffices to try once! */
909                 }
910                 while((d = readdir(mods))) {
911                         int ld = strlen(d->d_name);
912                         /* Must end in .so to load it.  */
913                         if (ld > 3 && (!base || !strncasecmp(d->d_name, base, lx)) && 
914                                         !strcasecmp(d->d_name + ld - 3, ".so") &&
915                                         !resource_exists(d->d_name, 1)) {
916                                 /* It's a shared library, check if we are allowed to load it
917                                  * (very inefficient, but oh well).
918                                  */
919                                 if (cfg) {
920                                         struct ast_variable *v;
921                                         for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
922                                                 if (!strcasecmp(v->name, "noload") &&
923                                                                 !strcasecmp(v->value, d->d_name)) 
924                                                         break;
925                                         }
926                                         if (v) {
927                                                 if (option_verbose) {
928                                                         ast_verbose( VERBOSE_PREFIX_1 "[skipping %s]\n",
929                                                                         d->d_name);
930                                                         fflush(stdout);
931                                                 }
932                                                 continue;
933                                         }
934                                         
935                                 }
936                                 if (print_and_load(d->d_name, cfg)) {
937                                         ast_config_destroy(cfg);
938                                         return -1;
939                                 }
940                         }
941                 }
942                 closedir(mods);
943         }
944 done:
945         fixup("load_modules");
946         ast_config_destroy(cfg);
947         return 0;
948 }
949
950 void ast_update_use_count(void)
951 {
952         /* Notify any module monitors that the use count for a 
953            resource has changed */
954         struct loadupdate *m;
955         if (AST_LIST_LOCK(&module_list))
956                 ast_log(LOG_WARNING, "Failed to lock\n");
957         AST_LIST_TRAVERSE(&updaters, m, next)
958                 m->updater();
959         AST_LIST_UNLOCK(&module_list);
960 }
961
962 int ast_update_module_list(int (*modentry)(const char *module, const char *description, int usecnt, const char *like),
963                            const char *like)
964 {
965         struct module *cur;
966         int unlock = -1;
967         int total_mod_loaded = 0;
968
969         if (ast_mutex_trylock(&module_list.lock))
970                 unlock = 0;
971         AST_LIST_TRAVERSE(&module_list, cur, next)
972                 total_mod_loaded += modentry(cur->resource, cur->cb.description(), cur->cb.usecount(), like);
973         if (unlock)
974                 AST_LIST_UNLOCK(&module_list);
975
976         return total_mod_loaded;
977 }
978
979 int ast_loader_register(int (*v)(void)) 
980 {
981         /* XXX Should be more flexible here, taking > 1 verboser XXX */
982         struct loadupdate *tmp; 
983         if (!(tmp = ast_malloc(sizeof(*tmp))))
984                 return -1;
985         tmp->updater = v;
986         if (AST_LIST_LOCK(&module_list))
987                 ast_log(LOG_WARNING, "Failed to lock\n");
988         AST_LIST_INSERT_HEAD(&updaters, tmp, next);
989         AST_LIST_UNLOCK(&module_list);
990         return 0;
991 }
992
993 int ast_loader_unregister(int (*v)(void))
994 {
995         struct loadupdate *cur;
996
997         if (AST_LIST_LOCK(&module_list))
998                 ast_log(LOG_WARNING, "Failed to lock\n");
999         AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, next) {
1000                 if (cur->updater == v)  {
1001                         AST_LIST_REMOVE_CURRENT(&updaters, next);
1002                         break;
1003                 }
1004         }
1005         AST_LIST_TRAVERSE_SAFE_END;
1006         AST_LIST_UNLOCK(&module_list);
1007         return cur ? 0 : -1;
1008 }