File: module.c

package info (click to toggle)
gnusound 0.6.2-5
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 2,488 kB
  • ctags: 1,778
  • sloc: ansic: 21,146; sh: 2,505; xml: 527; makefile: 171; perl: 157
file content (161 lines) | stat: -rw-r--r-- 3,957 bytes parent folder | download
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;
}