src/module.c
changeset 108 50ff7ac8a725
parent 103 454aea1e4f11
child 110 43e9a7984955
equal deleted inserted replaced
107:5c1eeb45c7f2 108:50ff7ac8a725
     1 #include "module.h"
     1 #include "module.h"
     2 #include "log.h"
     2 #include "log.h"
     3 
     3 
     4 #include <stdlib.h>
     4 #include <stdlib.h>
       
     5 #include <unistd.h>
     5 #include <dlfcn.h>
     6 #include <dlfcn.h>
     6 #include <string.h>
     7 #include <string.h>
     7 #include <assert.h>
     8 #include <assert.h>
     8 
     9 
     9 err_t modules_create (struct modules **modules_ptr, struct nexus *nexus)
    10 err_t modules_create (struct modules **modules_ptr, struct nexus *nexus)
    22 
    23 
    23     // ok
    24     // ok
    24     *modules_ptr = modules;
    25     *modules_ptr = modules;
    25 
    26 
    26     return SUCCESS;
    27     return SUCCESS;
       
    28 }
       
    29 
       
    30 const char* modules_path (struct modules *modules, const char *path)
       
    31 {
       
    32     const char *old_path = modules->path;
       
    33 
       
    34     if (path)
       
    35         // replace
       
    36         modules->path = path;
       
    37 
       
    38     return old_path;
    27 }
    39 }
    28 
    40 
    29 const char* module_name (struct module *module)
    41 const char* module_name (struct module *module)
    30 {
    42 {
    31     return module->info.name;
    43     return module->info.name;
    51 
    63 
    52     // ok
    64     // ok
    53     return SUCCESS;
    65     return SUCCESS;
    54 }
    66 }
    55 
    67 
    56 err_t module_load (struct modules *modules, struct module **module_ptr, const struct module_info *info, struct error_info *err)
    68 /**
       
    69  * XXX: ugly function to format to a dynamically allocated string
       
    70  */
       
    71 char *strfmt (const char *fmt, ...)
       
    72 {
       
    73     va_list vargs;
       
    74     size_t len;
       
    75     char *buf;
       
    76 
       
    77     // figure out the length of the resulting string
       
    78     va_start(vargs, fmt);
       
    79 
       
    80     len = vsnprintf(NULL, 0, fmt, vargs) + 1;
       
    81 
       
    82     va_end(vargs);
       
    83 
       
    84     // malloc
       
    85     if ((buf = malloc(len)) == NULL)
       
    86         return NULL;
       
    87 
       
    88     // format
       
    89     va_start(vargs, fmt);
       
    90 
       
    91     vsnprintf(buf, len, fmt, vargs);
       
    92 
       
    93     va_end(vargs);
       
    94 
       
    95     // ok
       
    96     return buf;
       
    97 }
       
    98 
       
    99 /**
       
   100  * Looks up a module's path by name, returning a dynamically allocated string with the path on success
       
   101  */
       
   102 static char* module_find (struct modules *modules, struct module_info *info, struct error_info *err)
       
   103 {
       
   104     char *path = NULL;
       
   105 
       
   106     // build the path...
       
   107     if ((path = strfmt("%s/mod_%s.so", modules->path, info->name)) == NULL)
       
   108         JUMP_SET_ERROR(err, ERR_STRDUP);
       
   109 
       
   110     // exists and readable?
       
   111     if (access(path, R_OK))
       
   112         // XXX: this doesn't contain the path...
       
   113         JUMP_SET_ERROR_STR(err, ERR_MODULE_PATH, "module not found in search path");
       
   114     
       
   115     // ok
       
   116     return path;
       
   117 
       
   118 error:
       
   119     // release the dynamically allocated path
       
   120     free(path);
       
   121 
       
   122     return NULL;
       
   123 }
       
   124 
       
   125 err_t module_load (struct modules *modules, struct module **module_ptr, const struct module_info *_info, struct error_info *err)
    57 {
   126 {
    58     struct module *module;
   127     struct module *module;
    59 
   128 
    60     // validate the module name
   129     // validate the module name
    61     if (strlen(info->name) > MODULE_NAME_MAX)
   130     if (strlen(_info->name) > MODULE_NAME_MAX)
    62         return SET_ERROR(err, ERR_MODULE_NAME);
   131         return SET_ERROR(err, ERR_MODULE_NAME);
    63     
   132     
       
   133     // already open with the same name?
       
   134     if (module_get(modules, _info->name))
       
   135         return SET_ERROR(err, ERR_MODULE_DUP);
       
   136 
    64     // alloc
   137     // alloc
    65     if ((module = calloc(1, sizeof(*module))) == NULL)
   138     if ((module = calloc(1, sizeof(*module))) == NULL)
    66         return SET_ERROR(err, ERR_CALLOC);
   139         return SET_ERROR(err, ERR_CALLOC);
    67     
   140     
    68     // store
   141     // store
    69     module->info = *info;
   142     module->info = *_info;
    70     module->modules = modules;
   143     module->modules = modules;
       
   144  
       
   145     // add to modules list
       
   146     TAILQ_INSERT_TAIL(&modules->list, module, modules_list);
       
   147    
       
   148     // lookup path?
       
   149     if (!module->info.path) {
       
   150         // have a search path?
       
   151         if (!modules->path)
       
   152             JUMP_SET_ERROR_STR(err, ERR_MODULE_PATH, "no module search path defined");
       
   153 
       
   154         // try and resolve the path automatically
       
   155         if ((module->path_buf = module_find(modules, &module->info, err)) == NULL)
       
   156             goto error;
       
   157         
       
   158         // use that path
       
   159         module->info.path = module->path_buf;
       
   160     }
    71 
   161 
    72     // clear dlerrors
   162     // clear dlerrors
    73     (void) dlerror();
   163     (void) dlerror();
    74 
   164 
    75     // load it
   165     // load it
    76     if ((module->handle = dlopen(info->path, RTLD_NOW)) == NULL)
   166     if ((module->handle = dlopen(module->info.path, RTLD_NOW)) == NULL)
    77         JUMP_SET_ERROR_STR(err, ERR_MODULE_OPEN, dlerror());
   167         JUMP_SET_ERROR_STR(err, ERR_MODULE_OPEN, dlerror());
    78     
   168     
    79     // load the funcs symbol
   169     // load the funcs symbol
    80     if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->desc, "module")))
   170     if ((ERROR_CODE(err) = module_symbol(module, (void **) &module->desc, "module")))
    81         JUMP_SET_ERROR_STR(err, ERROR_CODE(err), dlerror());
   171         JUMP_SET_ERROR_STR(err, ERROR_CODE(err), dlerror());
    82 
   172 
    83     // call the init func
   173     // call the init func
    84     if ((module->desc->init(modules->nexus, &module->ctx, err)))
   174     if ((module->desc->init(modules->nexus, &module->ctx, err)))
    85         goto error;
   175         goto error;
    86 
   176 
    87     // add to modules list
       
    88     TAILQ_INSERT_TAIL(&modules->list, module, modules_list);
       
    89 
       
    90     // ok
   177     // ok
    91     if (module_ptr)
   178     if (module_ptr)
    92         *module_ptr = module;
   179         *module_ptr = module;
    93 
   180 
    94     return SUCCESS;
   181     return SUCCESS;
    95 
   182 
    96 error:
   183 error:
    97     // XXX: cleanup
   184     // cleanup
    98     free(module);
   185     module_destroy(module);
    99 
   186 
   100     return ERROR_CODE(err);    
   187     return ERROR_CODE(err);    
   101 }
   188 }
   102 
   189 
   103 struct module* module_get (struct modules *modules, const char *name)
   190 struct module* module_get (struct modules *modules, const char *name)
   170 {
   257 {
   171     // remove from modules list
   258     // remove from modules list
   172     TAILQ_REMOVE(&module->modules->list, module, modules_list);
   259     TAILQ_REMOVE(&module->modules->list, module, modules_list);
   173 
   260 
   174     // unload the dl handle
   261     // unload the dl handle
   175     if (dlclose(module->handle))
   262     if (module->handle && dlclose(module->handle))
   176         log_error("dlclose(%s): %s", module->info.name, dlerror());
   263         log_error("dlclose(%s): %s", module->info.name, dlerror());
   177     
   264     
       
   265     // release the path buf, if any
       
   266     free(module->path_buf);
       
   267 
   178     // free the module info
   268     // free the module info
   179     free(module);
   269     free(module);
   180 }
   270 }
   181 
   271 
   182 err_t modules_unload (struct modules *modules)
   272 err_t modules_unload (struct modules *modules)