1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
/*
* Copyright (C) 2002,2003 Pascal Haakmat.
* Licensed under the GNU GPL.
* Absolutely no warranty.
*/
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <wordexp.h>
#include <config.h>
#include "module.h"
module modules[MAX_MODULES];
int module_count = 0;
void
module_exit() {
int i;
// void (*module_dtor)(module *mod);
for(i = 0; i < module_count; i++) {
DEBUG("destroying module '%s'\n", modules[i].name);
/* FIXME */
// module_dtor = dlsym(modules[i].handle, "module_destroy");
// if(module_dtor)
// (*module_dtor)(mod);
dlclose(modules[i].handle);
free(modules[i].author);
free(modules[i].copyright);
free(modules[i].name);
free(modules[i].fname);
}
}
void
module_load(const char *path) {
void *handle;
char *error;
module *mod;
module *(*module_ctor)();
void (*module_dtor)(module *mod);
if(module_count + 1 >= MAX_MODULES) {
FAIL("won't load %s because maximum number of modules exceeded.\n",
path);
return;
}
handle = dlopen(path, RTLD_NOW);
if (!handle) {
//FAIL("could not open %s: %s\n", path, dlerror());
return;
}
module_ctor = dlsym(handle, "module_new");
if((error = dlerror()) != NULL) {
//FAIL("could not open %s: %s\n", path, error);
dlclose(handle);
return;
}
mod = (*module_ctor)();
if(!mod || mod->error) {
FAIL("failed to create module. %s.\n",
mod ? mod->error : "unspecified error");
dlclose(handle);
return;
}
// DEBUG("%s: version: %x; MODULE_API_VERSION: %x\n",
// path, mod->version, MODULE_API_VERSION);
if(mod->magic != MODULE_MAGIC ||
(mod->version & 0xFF00) < (MODULE_API_VERSION & 0xFF00)) {
if(mod->magic != MODULE_MAGIC)
FAIL("%s: magic does not match: %x\n",
path, mod->magic);
else
FAIL("%s: version does not match\n",
path);
module_dtor = dlsym(handle, "module_destroy");
if(module_dtor)
(*module_dtor)(mod);
dlclose(handle);
return;
}
modules[module_count].name = strdup(mod->name);
modules[module_count].author = strdup(mod->author);
modules[module_count].copyright = strdup(mod->copyright);
modules[module_count].fname = strdup(path);
modules[module_count].handle = handle;
module_count++;
DEBUG("created module %d, '%s'\n", module_count, mod->name);
}
int
module_compare(const void *a,
const void *b) {
return strcmp(((module *)a)->name, ((module *)b)->name);
}
int
module_collect(const char *path) {
char tmp[512];
struct dirent **namelist;
int i, n;
n = scandir(path, &namelist, 0, alphasort);
if (n < 0) {
FAIL("unable to load modules in %s: %s\n", path, strerror(errno));
return 0;
}
for(i = 0; i < n; i++) {
snprintf(tmp, 512, "%s/%s", path, namelist[i]->d_name);
free(namelist[i]);
module_load(tmp);
}
free(namelist);
qsort(modules, module_count, sizeof(module), module_compare);
return 0;
}
int
module_init() {
int i, r;
char *sp = strdup(MODULE_PATH), *t, *sp2;
wordexp_t exp;
if(!sp) {
FAIL("unable to initialize modules, not enough memory to copy MODULE_PATH, bye\n");
return 1;
}
sp2 = sp;
while((t = strsep(&sp, ":"))) {
r = wordexp(t, &exp, 0);
if(r) {
FAIL("unable to initalize modules in path %s, invalid path?\n",
t);
continue;
}
DEBUG("collecting modules in path %s\n", t);
for(i = 0; i < exp.we_wordc; i++) {
DEBUG("expansion %d: %s\n", i, exp.we_wordv[i]);
module_collect(exp.we_wordv[i]);
}
wordfree(&exp);
}
free(sp2);
return 0;
}
|