Wed Oct 28 15:49:03 2009

Asterisk developer's documentation


loader.c File Reference

Module Loader. More...

#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cdr.h"
#include "asterisk/enum.h"
#include "asterisk/rtp.h"
#include "asterisk/lock.h"
#include <dlfcn.h>
#include "asterisk/md5.h"

Include dependency graph for loader.c:

Go to the source code of this file.

Data Structures

struct  loadupdate
struct  module

Defines

#define RTLD_NOW   0

Functions

static int __load_resource (const char *resource_name, const struct ast_config *cfg)
int ast_load_resource (const char *resource_name)
 Load a module.
int ast_loader_register (int(*v)(void))
 Add a procedure to be run when modules have been updated.
int ast_loader_unregister (int(*v)(void))
 Remove a procedure to be run when modules are updated.
char * ast_module_helper (char *line, char *word, int pos, int state, int rpos, int needsreload)
 Match modules names for the Asterisk cli.
int ast_module_reload (const char *name)
 Reload asterisk modules.
 AST_MUTEX_DEFINE_STATIC (reloadlock)
 AST_MUTEX_DEFINE_STATIC (modlock)
static int ast_resource_exists (char *resource)
int ast_unload_resource (const char *resource_name, int force)
 Unloads a module.
int ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *like), const char *like)
 Ask for a list of modules, descriptions, and use counts.
void ast_update_use_count (void)
 Notify when usecount has been changed.
static int key_matches (unsigned char *key1, unsigned char *key2)
int load_modules (const int preload_only)
static int printdigest (unsigned char *d)
static int verify_key (unsigned char *key)

Variables

static unsigned char expected_key []
static const char * loadorder []
static int modlistver = 0
static struct modulemodule_list = NULL
static struct loadupdateupdaters


Detailed Description

Module Loader.

Definition in file loader.c.


Define Documentation

#define RTLD_NOW   0

Definition at line 54 of file loader.c.

Referenced by __load_resource(), dlopen(), and loadModule().


Function Documentation

static int __load_resource ( const char *  resource_name,
const struct ast_config cfg 
) [static]

Definition at line 271 of file loader.c.

References ast_config_AST_MODULE_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_unload_resource(), ast_update_use_count(), ast_variable_retrieve(), ast_verbose(), COLOR_BLACK, COLOR_BROWN, module::description, dlclose(), dlerror(), dlopen(), dlsym(), free, fully_booted, module::key, key(), module::lib, module::load_module, LOG_WARNING, malloc, module::next, option_console, option_verbose, module::reload, module::resource, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, term_color(), module::unload_module, module::usecount, VERBOSE_PREFIX_1, and verify_key().

Referenced by ast_load_resource(), and load_modules().

00272 {
00273    static char fn[256];
00274    int errors=0;
00275    int res;
00276    struct module *m;
00277    int flags=RTLD_NOW;
00278 #ifdef RTLD_GLOBAL
00279    char *val;
00280 #endif
00281    unsigned char *key;
00282    char tmp[80];
00283 
00284    if (strncasecmp(resource_name, "res_", 4)) {
00285 #ifdef RTLD_GLOBAL
00286       if (cfg) {
00287          if ((val = ast_variable_retrieve(cfg, "global", resource_name))
00288                && ast_true(val))
00289             flags |= RTLD_GLOBAL;
00290       }
00291 #endif
00292    } else {
00293       /* Resource modules are always loaded global and lazy */
00294 #ifdef RTLD_GLOBAL
00295       flags = (RTLD_GLOBAL | RTLD_LAZY);
00296 #else
00297       flags = RTLD_LAZY;
00298 #endif
00299    }
00300    
00301    if (ast_mutex_lock(&modlock))
00302       ast_log(LOG_WARNING, "Failed to lock\n");
00303    m = module_list;
00304    while(m) {
00305       if (!strcasecmp(m->resource, resource_name)) {
00306          ast_log(LOG_WARNING, "Module '%s' already exists\n", resource_name);
00307          ast_mutex_unlock(&modlock);
00308          return -1;
00309       }
00310       m = m->next;
00311    }
00312    m = malloc(sizeof(struct module));  
00313    if (!m) {
00314       ast_log(LOG_WARNING, "Out of memory\n");
00315       ast_mutex_unlock(&modlock);
00316       return -1;
00317    }
00318    strncpy(m->resource, resource_name, sizeof(m->resource)-1);
00319    if (resource_name[0] == '/') {
00320       strncpy(fn, resource_name, sizeof(fn)-1);
00321    } else {
00322       snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_MODULE_DIR, resource_name);
00323    }
00324    m->lib = dlopen(fn, flags);
00325    if (!m->lib) {
00326       ast_log(LOG_WARNING, "%s\n", dlerror());
00327       free(m);
00328       ast_mutex_unlock(&modlock);
00329       return -1;
00330    }
00331    m->load_module = dlsym(m->lib, "load_module");
00332    if (m->load_module == NULL)
00333       m->load_module = dlsym(m->lib, "_load_module");
00334    if (!m->load_module) {
00335       ast_log(LOG_WARNING, "No load_module in module %s\n", fn);
00336       errors++;
00337    }
00338    m->unload_module = dlsym(m->lib, "unload_module");
00339    if (m->unload_module == NULL)
00340       m->unload_module = dlsym(m->lib, "_unload_module");
00341    if (!m->unload_module) {
00342       ast_log(LOG_WARNING, "No unload_module in module %s\n", fn);
00343       errors++;
00344    }
00345    m->usecount = dlsym(m->lib, "usecount");
00346    if (m->usecount == NULL)
00347       m->usecount = dlsym(m->lib, "_usecount");
00348    if (!m->usecount) {
00349       ast_log(LOG_WARNING, "No usecount in module %s\n", fn);
00350       errors++;
00351    }
00352    m->description = dlsym(m->lib, "description");
00353    if (m->description == NULL)
00354       m->description = dlsym(m->lib, "_description");
00355    if (!m->description) {
00356       ast_log(LOG_WARNING, "No description in module %s\n", fn);
00357       errors++;
00358    }
00359    m->key = dlsym(m->lib, "key");
00360    if (m->key == NULL)
00361       m->key = dlsym(m->lib, "_key");
00362    if (!m->key) {
00363       ast_log(LOG_WARNING, "No key routine in module %s\n", fn);
00364       errors++;
00365    }
00366 
00367    m->reload = dlsym(m->lib, "reload");
00368    if (m->reload == NULL)
00369       m->reload = dlsym(m->lib, "_reload");
00370 
00371    if (!m->key || !(key = (unsigned char *) m->key())) {
00372       ast_log(LOG_WARNING, "Key routine returned NULL in module %s\n", fn);
00373       key = NULL;
00374       errors++;
00375    }
00376    if (key && verify_key(key)) {
00377       ast_log(LOG_WARNING, "Unexpected key returned by module %s\n", fn);
00378       errors++;
00379    }
00380    if (errors) {
00381       ast_log(LOG_WARNING, "%d error%s loading module %s, aborted\n", errors, (errors != 1) ? "s" : "", fn);
00382       dlclose(m->lib);
00383       free(m);
00384       ast_mutex_unlock(&modlock);
00385       return -1;
00386    }
00387    if (!fully_booted) {
00388       if (option_verbose) 
00389          ast_verbose( " => (%s)\n", term_color(tmp, m->description(), COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00390       if (option_console && !option_verbose)
00391          ast_verbose( ".");
00392    } else {
00393       if (option_verbose)
00394          ast_verbose(VERBOSE_PREFIX_1 "Loaded %s => (%s)\n", fn, m->description());
00395    }
00396 
00397    /* add module 'm' to end of module_list chain
00398       so reload commands will be issued in same order modules were loaded */
00399    m->next = NULL;
00400    if (module_list == NULL) {
00401       /* empty list so far, add at front */
00402       module_list = m;
00403    }
00404    else {
00405       struct module *i;
00406       /* find end of chain, and add there */
00407       for (i = module_list; i->next; i = i->next)
00408          ;
00409       i->next = m;
00410    }
00411    
00412    modlistver = rand();
00413    ast_mutex_unlock(&modlock);
00414    if ((res = m->load_module())) {
00415       ast_log(LOG_WARNING, "%s: load_module failed, returning %d\n", m->resource, res);
00416       ast_unload_resource(resource_name, 0);
00417       return -1;
00418    }
00419    ast_update_use_count();
00420    return 0;
00421 }

int ast_load_resource ( const char *  resource_name  ) 

Load a module.

Parameters:
resource_name The filename of the module to load.
This function is run by the PBX to load the modules. It performs all loading and initilization tasks. Basically, to load a module, just give it the name of the module and it will do the rest.

Returns:
Zero on success, -1 on error.

Definition at line 423 of file loader.c.

References __load_resource(), ast_config_destroy(), ast_config_load(), AST_MODULE_CONFIG, cfg, and option_verbose.

Referenced by file_ok_sel(), handle_load(), load_module(), and reload_module().

00424 {
00425    int o;
00426    struct ast_config *cfg = NULL;
00427    int res;
00428 
00429    /* Keep the module file parsing silent */
00430    o = option_verbose;
00431    option_verbose = 0;
00432    cfg = ast_config_load(AST_MODULE_CONFIG);
00433    option_verbose = o;
00434    res = __load_resource(resource_name, cfg);
00435    if (cfg)
00436       ast_config_destroy(cfg);
00437    return res;
00438 }  

int ast_loader_register ( int(*)(void)  updater  ) 

Add a procedure to be run when modules have been updated.

Parameters:
updater The function to run when modules have been updated.
This function adds the given function to a linked list of functions to be run when the modules are updated.

Returns:
Zero on success and -1 on failure.

Definition at line 609 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, malloc, loadupdate::next, loadupdate::updater, and updaters.

Referenced by show_console().

00610 {
00611    struct loadupdate *tmp;
00612    /* XXX Should be more flexible here, taking > 1 verboser XXX */
00613    if ((tmp = malloc(sizeof (struct loadupdate)))) {
00614       tmp->updater = v;
00615       if (ast_mutex_lock(&modlock))
00616          ast_log(LOG_WARNING, "Failed to lock\n");
00617       tmp->next = updaters;
00618       updaters = tmp;
00619       ast_mutex_unlock(&modlock);
00620       return 0;
00621    }
00622    return -1;
00623 }

int ast_loader_unregister ( int(*)(void)  updater  ) 

Remove a procedure to be run when modules are updated.

Parameters:
updater The updater function to unregister.
This removes the given function from the updater list.

Returns:
Zero on success, -1 on failure.

Definition at line 625 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, loadupdate::next, loadupdate::updater, and updaters.

Referenced by exit_now().

00626 {
00627    int res = -1;
00628    struct loadupdate *tmp, *tmpl=NULL;
00629    if (ast_mutex_lock(&modlock))
00630       ast_log(LOG_WARNING, "Failed to lock\n");
00631    tmp = updaters;
00632    while(tmp) {
00633       if (tmp->updater == v)  {
00634          if (tmpl)
00635             tmpl->next = tmp->next;
00636          else
00637             updaters = tmp->next;
00638          break;
00639       }
00640       tmpl = tmp;
00641       tmp = tmp->next;
00642    }
00643    if (tmp)
00644       res = 0;
00645    ast_mutex_unlock(&modlock);
00646    return res;
00647 }

char* ast_module_helper ( char *  line,
char *  word,
int  pos,
int  state,
int  rpos,
int  needsreload 
)

Match modules names for the Asterisk cli.

Parameters:
line Unused by this function, but this should be the line we are matching.
word The partial name to match.
pos The position the word we are completing is in.
state The possible match to return.
rpos The position we should be matching. This should be the same as pos.
needsreload This should be 1 if we need to reload this module and 0 otherwise. This function will only return modules that are reloadble if this is 1.
Returns:
A possible completion of the partial match, or NULL if no matches were found.

Definition at line 166 of file loader.c.

References ast_mutex_lock(), ast_mutex_unlock(), module::next, module::reload, module::resource, and strdup.

Referenced by complete_mod_2(), and complete_mod_4().

00167 {
00168    struct module *m;
00169    int which=0;
00170    char *ret;
00171 
00172    if (pos != rpos)
00173       return NULL;
00174    ast_mutex_lock(&modlock);
00175    m = module_list;
00176    while(m) {
00177       if (!strncasecmp(word, m->resource, strlen(word)) && (m->reload || !needsreload)) {
00178          if (++which > state)
00179             break;
00180       }
00181       m = m->next;
00182    }
00183    if (m) {
00184       ret = strdup(m->resource);
00185    } else {
00186       ret = NULL;
00187       if (!strncasecmp(word, "extconfig", strlen(word))) {
00188          if (++which > state)
00189             ret = strdup("extconfig");
00190       } else if (!strncasecmp(word, "manager", strlen(word))) {
00191          if (++which > state)
00192             ret = strdup("manager");
00193       } else if (!strncasecmp(word, "enum", strlen(word))) {
00194          if (++which > state)
00195             ret = strdup("enum");
00196       } else if (!strncasecmp(word, "rtp", strlen(word))) {
00197          if (++which > state)
00198             ret = strdup("rtp");
00199       }
00200          
00201    }
00202    ast_mutex_unlock(&modlock);
00203    return ret;
00204 }

int ast_module_reload ( const char *  name  ) 

Reload asterisk modules.

Parameters:
name the name of the module to reload
This function reloads the specified module, or if no modules are specified, it will reload all loaded modules.

Note:
Modules are reloaded using their reload() functions, not unloading them and loading them again.
Returns:
Zero if the specified module was not found, 1 if the module was found but cannot be reloaded, -1 if a reload operation is already in progress, and 2 if the specfied module was found and reloaded.

Definition at line 206 of file loader.c.

References ast_cdr_engine_reload(), ast_enum_reload(), ast_lastreloadtime, ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_rtp_reload(), ast_verbose(), module::description, dnsmgr_reload(), module::next, option_verbose, read_config_maps(), module::reload, reload(), reload_manager(), module::resource, and VERBOSE_PREFIX_3.

Referenced by handle_reload(), and monitor_sig_flags().

00207 {
00208    struct module *m;
00209    int reloaded = 0;
00210    int oldversion;
00211    int (*reload)(void);
00212    /* We'll do the logger and manager the favor of calling its reload here first */
00213 
00214    if (ast_mutex_trylock(&reloadlock)) {
00215       ast_verbose("The previous reload command didn't finish yet\n");
00216       return -1;
00217    }
00218    time(&ast_lastreloadtime);
00219 
00220    if (!name || !strcasecmp(name, "extconfig")) {
00221       read_config_maps();
00222       reloaded = 2;
00223    }
00224    if (!name || !strcasecmp(name, "manager")) {
00225       reload_manager();
00226       reloaded = 2;
00227    }
00228    if (!name || !strcasecmp(name, "cdr")) {
00229       ast_cdr_engine_reload();
00230       reloaded = 2;
00231    }
00232    if (!name || !strcasecmp(name, "enum")) {
00233       ast_enum_reload();
00234       reloaded = 2;
00235    }
00236    if (!name || !strcasecmp(name, "rtp")) {
00237       ast_rtp_reload();
00238       reloaded = 2;
00239    }
00240    if (!name || !strcasecmp(name, "dnsmgr")) {
00241       dnsmgr_reload();
00242       reloaded = 2;
00243    }
00244 
00245    ast_mutex_lock(&modlock);
00246    oldversion = modlistver;
00247    m = module_list;
00248    while(m) {
00249       if (!name || !strcasecmp(name, m->resource)) {
00250          if (reloaded < 1)
00251             reloaded = 1;
00252          reload = m->reload;
00253          ast_mutex_unlock(&modlock);
00254          if (reload) {
00255             reloaded = 2;
00256             if (option_verbose > 2) 
00257                ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", m->resource, m->description());
00258             reload();
00259          }
00260          ast_mutex_lock(&modlock);
00261          if (oldversion != modlistver)
00262             break;
00263       }
00264       m = m->next;
00265    }
00266    ast_mutex_unlock(&modlock);
00267    ast_mutex_unlock(&reloadlock);
00268    return reloaded;
00269 }

AST_MUTEX_DEFINE_STATIC ( reloadlock   ) 

AST_MUTEX_DEFINE_STATIC ( modlock   ) 

static int ast_resource_exists ( char *  resource  )  [static]

Definition at line 440 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, module::next, and module::resource.

Referenced by load_modules().

00441 {
00442    struct module *m;
00443    if (ast_mutex_lock(&modlock))
00444       ast_log(LOG_WARNING, "Failed to lock\n");
00445    m = module_list;
00446    while(m) {
00447       if (!strcasecmp(resource, m->resource))
00448          break;
00449       m = m->next;
00450    }
00451    ast_mutex_unlock(&modlock);
00452    if (m)
00453       return -1;
00454    else
00455       return 0;
00456 }

int ast_unload_resource ( const char *  resource_name,
int  force 
)

Unloads a module.

Parameters:
resource_name The name of the module to unload.
force The force flag. This should be set using one of the AST_FORCE* flags.
This function unloads a module. It will only unload modules that are not in use (usecount not zero), unless AST_FORCE_FIRM or AST_FORCE_HARD is specified. Setting AST_FORCE_FIRM or AST_FORCE_HARD will unload the module regardless of consequences (NOT_RECOMMENDED).

Returns:
Zero on success, -1 on error.

Definition at line 122 of file loader.c.

References AST_FORCE_FIRM, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), dlclose(), free, module::lib, LOG_WARNING, module::next, module::resource, module::unload_module, and module::usecount.

Referenced by __load_resource(), exit_now(), handle_unload(), reload_module(), and remove_module().

00123 {
00124    struct module *m, *ml = NULL;
00125    int res = -1;
00126    if (ast_mutex_lock(&modlock))
00127       ast_log(LOG_WARNING, "Failed to lock\n");
00128    m = module_list;
00129    while(m) {
00130       if (!strcasecmp(m->resource, resource_name)) {
00131          if ((res = m->usecount()) > 0)  {
00132             if (force) 
00133                ast_log(LOG_WARNING, "Warning:  Forcing removal of module %s with use count %d\n", resource_name, res);
00134             else {
00135                ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, res);
00136                ast_mutex_unlock(&modlock);
00137                return -1;
00138             }
00139          }
00140          res = m->unload_module();
00141          if (res) {
00142             ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00143             if (force <= AST_FORCE_FIRM) {
00144                ast_mutex_unlock(&modlock);
00145                return -1;
00146             } else
00147                ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00148          }
00149          if (ml)
00150             ml->next = m->next;
00151          else
00152             module_list = m->next;
00153          dlclose(m->lib);
00154          free(m);
00155          break;
00156       }
00157       ml = m;
00158       m = m->next;
00159    }
00160    modlistver = rand();
00161    ast_mutex_unlock(&modlock);
00162    ast_update_use_count();
00163    return res;
00164 }

int ast_update_module_list ( int(*)(const char *module, const char *description, int usecnt, const char *like)  modentry,
const char *  like 
)

Ask for a list of modules, descriptions, and use counts.

Parameters:
modentry A callback to an updater function.
like For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module.
Returns:
the number of modules loaded

Definition at line 589 of file loader.c.

References ast_mutex_trylock(), ast_mutex_unlock(), module::description, module::next, module::resource, and module::usecount.

Referenced by handle_modlist(), and mod_update().

00591 {
00592    struct module *m;
00593    int unlock = -1;
00594    int total_mod_loaded = 0;
00595 
00596    if (ast_mutex_trylock(&modlock))
00597       unlock = 0;
00598    m = module_list;
00599    while (m) {
00600       total_mod_loaded += modentry(m->resource, m->description(), m->usecount(), like);
00601       m = m->next;
00602    }
00603    if (unlock)
00604       ast_mutex_unlock(&modlock);
00605 
00606    return total_mod_loaded;
00607 }

void ast_update_use_count ( void   ) 

Notify when usecount has been changed.

This function calulates use counts and notifies anyone trying to keep track of them. It should be called whenever your module's usecount changes.

Note:
The LOCAL_USER macros take care of calling this function for you.

Definition at line 573 of file loader.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, loadupdate::next, loadupdate::updater, and updaters.

Referenced by __load_resource(), __oh323_new(), adpcm_destroy(), adpcmtolin_new(), agent_new(), alaw_destroy(), alawtolin_new(), alawtoulaw_new(), alsa_new(), aopen_decusecnt(), aopen_incusecnt(), ast_iax2_new(), ast_modem_new(), ast_unload_resource(), au_close(), au_open(), au_rewrite(), bestdata_decusecnt(), bestdata_incusecnt(), exit_now(), features_new(), g723_close(), g723_destroy(), g723_open(), g723_rewrite(), g723tolin_new(), g726_16_open(), g726_16_rewrite(), g726_24_open(), g726_24_rewrite(), g726_32_open(), g726_32_rewrite(), g726_40_open(), g726_40_rewrite(), g726_close(), g726_destroy(), g726tolin_new(), g729_close(), g729_open(), g729_rewrite(), gsm_close(), gsm_open(), gsm_rewrite(), h263_close(), h263_open(), h263_rewrite(), i4l_decusecnt(), i4l_incusecnt(), iax2_predestroy(), ilbc_close(), ilbc_open(), ilbc_rewrite(), lintoadpcm_new(), lintoalaw_new(), lintog723_new(), lintog726_new(), lintoulaw_new(), load_module(), local_new(), mgcp_hangup(), mgcp_new(), modem_hangup(), nbs_new(), ogg_vorbis_close(), ogg_vorbis_open(), ogg_vorbis_rewrite(), oh323_hangup(), oh323_request(), oss_new(), pcm_close(), pcm_open(), pcm_rewrite(), phone_check_exception(), phone_hangup(), phone_new(), sip_hangup(), sip_new(), sip_request_call(), sipsock_read(), skinny_new(), slinear_close(), slinear_open(), slinear_rewrite(), ulaw_destroy(), ulawtoalaw_new(), ulawtolin_new(), vox_close(), vox_open(), vox_rewrite(), vpb_hangup(), vpb_new(), wav_close(), wav_open(), wav_rewrite(), zt_hangup(), and zt_new().

00574 {
00575    /* Notify any module monitors that the use count for a 
00576       resource has changed */
00577    struct loadupdate *m;
00578    if (ast_mutex_lock(&modlock))
00579       ast_log(LOG_WARNING, "Failed to lock\n");
00580    m = updaters;
00581    while(m) {
00582       m->updater();
00583       m = m->next;
00584    }
00585    ast_mutex_unlock(&modlock);
00586    
00587 }

static int key_matches ( unsigned char *  key1,
unsigned char *  key2 
) [static]

Definition at line 99 of file loader.c.

References match().

Referenced by verify_key().

00100 {
00101    int match = 1;
00102    int x;
00103    for (x=0; x<16; x++) {
00104       match &= (key1[x] == key2[x]);
00105    }
00106    return match;
00107 }

int load_modules ( const int  preload_only  ) 

Definition at line 466 of file loader.c.

References __load_resource(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load(), ast_log(), AST_MODULE_CONFIG, ast_resource_exists(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), cfg, COLOR_BRWHITE, LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, option_debug, option_quiet, option_verbose, term_color(), ast_variable::value, and VERBOSE_PREFIX_1.

Referenced by main().

00467 {
00468    struct ast_config *cfg;
00469    struct ast_variable *v;
00470    char tmp[80];
00471 
00472    if (option_verbose) {
00473       if (preload_only)
00474          ast_verbose("Asterisk Dynamic Loader loading preload modules:\n");
00475       else
00476          ast_verbose("Asterisk Dynamic Loader Starting:\n");
00477    }
00478 
00479    cfg = ast_config_load(AST_MODULE_CONFIG);
00480    if (cfg) {
00481       int doload;
00482 
00483       /* Load explicitly defined modules */
00484       for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
00485          doload = 0;
00486 
00487          if (preload_only)
00488             doload = !strcasecmp(v->name, "preload");
00489          else
00490             doload = !strcasecmp(v->name, "load");
00491 
00492              if (doload) {
00493             if (option_debug && !option_verbose)
00494                ast_log(LOG_DEBUG, "Loading module %s\n", v->value);
00495             if (option_verbose) {
00496                ast_verbose(VERBOSE_PREFIX_1 "[%s]", term_color(tmp, v->value, COLOR_BRWHITE, 0, sizeof(tmp)));
00497                fflush(stdout);
00498             }
00499             if (__load_resource(v->value, cfg)) {
00500                ast_log(LOG_WARNING, "Loading module %s failed!\n", v->value);
00501                ast_config_destroy(cfg);
00502                return -1;
00503             }
00504          }
00505       }
00506    }
00507 
00508    if (preload_only) {
00509       ast_config_destroy(cfg);
00510       return 0;
00511    }
00512 
00513    if (!cfg || ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
00514       /* Load all modules */
00515       DIR *mods;
00516       struct dirent *d;
00517       int x;
00518 
00519       /* Loop through each order */
00520       for (x=0; x<sizeof(loadorder) / sizeof(loadorder[0]); x++) {
00521          mods = opendir((char *)ast_config_AST_MODULE_DIR);
00522          if (mods) {
00523             while((d = readdir(mods))) {
00524                /* Must end in .so to load it.  */
00525                if ((strlen(d->d_name) > 3) && 
00526                    (!loadorder[x] || !strncasecmp(d->d_name, loadorder[x], strlen(loadorder[x]))) && 
00527                    !strcasecmp(d->d_name + strlen(d->d_name) - 3, ".so") &&
00528                   !ast_resource_exists(d->d_name)) {
00529                   /* It's a shared library -- Just be sure we're allowed to load it -- kinda
00530                      an inefficient way to do it, but oh well. */
00531                   if (cfg) {
00532                      v = ast_variable_browse(cfg, "modules");
00533                      while(v) {
00534                         if (!strcasecmp(v->name, "noload") &&
00535                             !strcasecmp(v->value, d->d_name)) 
00536                            break;
00537                         v = v->next;
00538                      }
00539                      if (v) {
00540                         if (option_verbose) {
00541                            ast_verbose( VERBOSE_PREFIX_1 "[skipping %s]\n", d->d_name);
00542                            fflush(stdout);
00543                         }
00544                         continue;
00545                      }
00546                      
00547                   }
00548                   if (option_debug && !option_verbose)
00549                      ast_log(LOG_DEBUG, "Loading module %s\n", d->d_name);
00550                   if (option_verbose) {
00551                      ast_verbose( VERBOSE_PREFIX_1 "[%s]", term_color(tmp, d->d_name, COLOR_BRWHITE, 0, sizeof(tmp)));
00552                      fflush(stdout);
00553                   }
00554                   if (__load_resource(d->d_name, cfg)) {
00555                      ast_log(LOG_WARNING, "Loading module %s failed!\n", d->d_name);
00556                      if (cfg)
00557                         ast_config_destroy(cfg);
00558                      return -1;
00559                   }
00560                }
00561             }
00562             closedir(mods);
00563          } else {
00564             if (!option_quiet)
00565                ast_log(LOG_WARNING, "Unable to open modules directory %s.\n", (char *)ast_config_AST_MODULE_DIR);
00566          }
00567       }
00568    } 
00569    ast_config_destroy(cfg);
00570    return 0;
00571 }

static int printdigest ( unsigned char *  d  )  [static]

Definition at line 84 of file loader.c.

References ast_log(), and LOG_DEBUG.

Referenced by verify_key().

00085 {
00086    int x;
00087    char buf[256];
00088    char buf2[16];
00089    snprintf(buf, sizeof(buf), "Unexpected signature:");
00090    for (x=0; x<16; x++) {
00091       snprintf(buf2, sizeof(buf2), " %02x", *(d++));
00092       strcat(buf, buf2);
00093    }
00094    strcat(buf, "\n");
00095    ast_log(LOG_DEBUG, "%s", buf);
00096    return 0;
00097 }

static int verify_key ( unsigned char *  key  )  [static]

Definition at line 109 of file loader.c.

References key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().

Referenced by __load_resource().

00110 {
00111    struct MD5Context c;
00112    unsigned char digest[16];
00113    MD5Init(&c);
00114    MD5Update(&c, key, strlen((char *)key));
00115    MD5Final(digest, &c);
00116    if (key_matches(expected_key, digest))
00117       return 0;
00118    printdigest(digest);
00119    return -1;
00120 }


Variable Documentation

unsigned char expected_key[] [static]

Initial value:

{ 0x8e, 0x93, 0x22, 0x83, 0xf5, 0xc3, 0xc0, 0x75,
  0xff, 0x8b, 0xa9, 0xbe, 0x7c, 0x43, 0x74, 0x63 }

Definition at line 63 of file loader.c.

const char* loadorder[] [static]

Definition at line 458 of file loader.c.

int modlistver = 0 [static]

Definition at line 61 of file loader.c.

struct module* module_list = NULL [static]

Definition at line 60 of file loader.c.

struct loadupdate * updaters [static]


Generated on Wed Oct 28 15:49:03 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6