This repository has been archived by the owner on Dec 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
module.cc
160 lines (141 loc) · 3.9 KB
/
module.cc
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
#include <stdio.h>
#include <dlfcn.h>
#include <pthread.h>
#include <dirent.h>
#include <string.h>
#include <string>
#include <map>
#include "module.h"
struct ModItem {
void * dlp;
void (*load)(void);
void (*unload)(void);
void (*serve)(const char *, char *);
};
pthread_rwlock_t list_rw_lock = PTHREAD_RWLOCK_INITIALIZER;
static std::map <std::string, struct ModItem> modules;
char mod_list[4096];
void mod_list_update(void) {
mod_list[0] = '\0';
std::map<std::string, struct ModItem>::iterator it = modules.begin();
for (; it != modules.end(); ++it) {
strcat(mod_list, it->first.c_str());
strcat(mod_list, "\n");
}
}
void mod_status(void){
fprintf(stderr, "All running modules:\n");
fprintf(stderr, mod_list);
}
void mod_candidates(const char * path){
DIR * dir;
struct dirent *ent;
if ((dir = opendir(path)) != NULL) {
fprintf(stderr, "module candidates:\n");
while ((ent = readdir(dir)) != NULL) {
if (ent->d_name[0] != '.')
fprintf(stderr, "\t%s", ent->d_name);
}
fprintf(stderr, "\n");
closedir(dir);
} else {
fprintf(stderr, "fail open module directory!\n");
}
}
bool mod_serve(const char * name, const char * param, char * target) {
std::string modname(name);
bool result = false;
int rl = pthread_rwlock_rdlock(&list_rw_lock);
if (modules.count(modname) > 0) {
modules[modname].serve(param, target);
result = true;
}
pthread_rwlock_unlock(&list_rw_lock);
return result;
}
void mod_doUnload(const char * name) {
fprintf(stderr, "try to unload module \'%s\'\n", name);
std::string modname(name);
// check if module exists
if (!modules.count(modname) > 0) {
fprintf(stderr, "no module named \'%s\'\n", name);
return;
}
// unregister module
fprintf(stderr, "unregistering module...");
struct ModItem mod = modules[modname];
modules.erase(modname);
mod_list_update();
fprintf(stderr, "done.\n");
// unload module
fprintf(stderr, "unloading module...");
mod.unload();
fprintf(stderr, "done.\n");
// close shared library
fprintf(stderr, "closing shared library...");
if (dlclose(mod.dlp)) {
fprintf(stderr, "fail\n");
char * errormsg = dlerror();
if (errormsg)
fprintf(stderr, errormsg);
} else {
fprintf(stderr, "done.\n");
fprintf(stderr, "SUCCESS!\n");
}
}
void mod_doLoad(const char * path) {
struct ModItem newmod;
std::string modname;
char * errormsg;
fprintf(stderr, "try to open library from file %s...", path);
// try load shared lib
newmod.dlp = dlopen(path, RTLD_LAZY);
if (newmod.dlp) {
fprintf(stderr, "done.\n");
// try get module information
fprintf(stderr, "try to getmodule information.\n");
const char * (* getName)(void) = (const char * (*)()) dlsym(newmod.dlp, "getName");
if (!getName) goto bad_mod;
modname = getName();
fprintf(stderr, "module name: %s\n", modname.c_str());
if (modules.count(modname) > 0) { // abort if name exists
fprintf(stderr, "module with same name having been loaded\n");
goto close_lib;
}
// try get interface
newmod.load = (void (*)()) dlsym(newmod.dlp, "load");
if (!newmod.load) goto bad_mod;
newmod.unload = (void (*)()) dlsym(newmod.dlp, "unload");
if (!newmod.unload) goto bad_mod;
newmod.serve = (void (*)(const char *, char *)) dlsym(newmod.dlp, "serve");
if (!newmod.serve) goto bad_mod;
// load module
fprintf(stderr, "loading module...");
newmod.load();
fprintf(stderr, "done.\n");
// register module
fprintf(stderr, "registering module...");
modules[modname] = newmod;
mod_list_update();
fprintf(stderr, "done.\n");
fprintf(stderr, "SUCCESS!\n");
return;
bad_mod:
fprintf(stderr, "BAD module.\n");
errormsg = dlerror();
if (errormsg)
fprintf(stderr, errormsg);
close_lib:
if (dlclose(newmod.dlp)) {
fprintf(stderr, "fail closing shared library.\n");
errormsg = dlerror();
if (errormsg)
fprintf(stderr, errormsg);
}
} else {
fprintf(stderr, "fail.\n");
errormsg = dlerror();
if (errormsg)
fprintf(stderr, errormsg);
}
}