Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / net-snmp / agent / mibgroup / misc / dlmod.c
1 #include <net-snmp/net-snmp-config.h>
2
3 #if HAVE_STDLIB_H
4 #include <stdlib.h>
5 #endif
6 #include <stdio.h>
7 #if HAVE_STRING_H
8 #include <string.h>
9 #else
10 #include <strings.h>
11 #endif
12 #if HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15 #include <ctype.h>
16 #if HAVE_NETINET_IN_H
17 #include <netinet/in.h>
18 #endif
19
20 #include <dlfcn.h>
21
22
23 #include <net-snmp/net-snmp-includes.h>
24 #include <net-snmp/agent/net-snmp-agent-includes.h>
25
26 #include "struct.h"
27
28 #include "dlmod.h"
29
30 static struct dlmod *dlmods = NULL;
31
32 int             dlmod_next_index = 1;
33
34 static void     dlmod_parse_config(char *, char *);
35 static void     dlmod_free_config(void);
36 static char     dlmod_path[1024];
37
38 void
39 init_dlmod(void)
40 {
41     char           *p;
42     int             l;
43
44     snmpd_register_config_handler("dlmod", dlmod_parse_config,
45                                   dlmod_free_config, "dlmod-file-to-load");
46
47     p = getenv("SNMP_DLMOD_PATH");
48     strncpy(dlmod_path, DLMOD_DEFAULT_PATH, sizeof(dlmod_path));
49     if (p) {
50         if (p[0] == '+') {
51             l = strlen(dlmod_path);
52             if (dlmod_path[l - 1] != ':')
53                 strncat(dlmod_path, ":", sizeof(dlmod_path) - l);
54             strncat(dlmod_path, p + 1,
55                     sizeof(dlmod_path) - strlen(dlmod_path));
56         } else
57             strncpy(dlmod_path, p, sizeof(dlmod_path));
58     }
59 #if 1
60     DEBUGMSGTL(("dlmod", "dlmod_path: %s\n", dlmod_path));
61 #endif
62 }
63
64 void
65 deinit_dlmod(void)
66 {
67     snmpd_unregister_config_handler("dlmod");
68 }
69
70 static void
71 dlmod_parse_config(char *token, char *cptr)
72 {
73     char           *dlm_name, *dlm_path;
74     struct dlmod   *dlm;
75
76     if (cptr == NULL) {
77         config_perror("Bad dlmod line");
78         return;
79     }
80     /*
81      * remove comments 
82      */
83     *(cptr + strcspn(cptr, "#;\r\n")) = '\0';
84
85     dlm = dlmod_create_module();
86     if (!dlm)
87         return;
88
89     /*
90      * dynamic module name 
91      */
92     dlm_name = strtok(cptr, "\t ");
93     if (dlm_name == NULL) {
94         config_perror("Bad dlmod line");
95         dlmod_delete_module(dlm);
96         return;
97     }
98     strncpy(dlm->name, dlm_name, sizeof(dlm->name));
99
100     /*
101      * dynamic module path 
102      */
103     dlm_path = strtok(NULL, "\t ");
104     if (dlm_path)
105         strncpy(dlm->path, dlm_path, sizeof(dlm->path));
106     else
107         strncpy(dlm->path, dlm_name, sizeof(dlm->path));
108
109     dlmod_load_module(dlm);
110
111     if (dlm->status == DLMOD_ERROR)
112         snmp_log(LOG_ERR, "%s\n", dlm->error);
113
114 }
115
116 static void
117 dlmod_free_config(void)
118 {
119     struct dlmod   *dtmp, *dtmp2;
120
121     for (dtmp = dlmods; dtmp != NULL;) {
122         dtmp2 = dtmp;
123         dtmp = dtmp->next;
124         dlmod_unload_module(dtmp2);
125         free(dtmp2);
126     }
127     dlmods = NULL;
128     dlmod_next_index = 1;
129 }
130
131 struct dlmod   *
132 dlmod_create_module(void)
133 {
134     struct dlmod  **pdlmod, *dlm;
135 #if 1
136     DEBUGMSGTL(("dlmod", "dlmod_create_module\n"));
137 #endif
138     dlm = calloc(1, sizeof(struct dlmod));
139     if (dlm == NULL)
140         return NULL;
141
142     dlm->index = dlmod_next_index++;
143     dlm->status = DLMOD_UNLOADED;
144
145     for (pdlmod = &dlmods; *pdlmod != NULL; pdlmod = &((*pdlmod)->next));
146     (*pdlmod) = dlm;
147
148     return dlm;
149 }
150
151 void
152 dlmod_delete_module(struct dlmod *dlm)
153 {
154     struct dlmod  **pdlmod;
155
156 #if 1
157     DEBUGMSGTL(("dlmod", "dlmod_delete_module\n"));
158 #endif
159     if (!dlm || dlm->status != DLMOD_UNLOADED)
160         return;
161
162     for (pdlmod = &dlmods; *pdlmod; pdlmod = &((*pdlmod)->next))
163         if (*pdlmod == dlm) {
164             *pdlmod = dlm->next;
165             free(dlm);
166             return;
167         }
168 }
169
170 void
171 dlmod_load_module(struct dlmod *dlm)
172 {
173     char            sym_init[64];
174     char           *p, tmp_path[255];
175     int             (*dl_init) (void);
176 #if 1
177     DEBUGMSGTL(("dlmod", "dlmod_load_module\n"));
178 #endif
179
180     if (!dlm || !dlm->path || !dlm->name || dlm->status != DLMOD_UNLOADED)
181         return;
182
183
184     if (dlm->path[0] == '/') {
185         dlm->handle = dlopen(dlm->path, RTLD_NOW);
186         if (dlm->handle == NULL) {
187             snprintf(dlm->error, sizeof(dlm->error),
188                      "dlopen failed: %s", dlerror());
189             dlm->status = DLMOD_ERROR;
190             return;
191         }
192     } else {
193         for (p = strtok(dlmod_path, ":"); p; p = strtok(NULL, ":")) {
194             snprintf(tmp_path, sizeof(tmp_path), "%s/%s.so", p, dlm->path);
195 #if 1
196             DEBUGMSGTL(("dlmod", "p: %s tmp_path: %s\n", p, tmp_path));
197 #endif
198             dlm->handle = dlopen(tmp_path, RTLD_NOW);
199             if (dlm->handle == NULL) {
200                 snprintf(dlm->error, sizeof(dlm->error),
201                          "dlopen failed: %s", dlerror());
202                 dlm->status = DLMOD_ERROR;
203             }
204         }
205         strncpy(dlm->path, tmp_path, sizeof(dlm->path));
206         if (dlm->status == DLMOD_ERROR)
207             return;
208     }
209     snprintf(sym_init, sizeof(sym_init), "_dynamic_init_%s", dlm->name);
210     dl_init = dlsym(dlm->handle, sym_init);
211     if (dl_init == NULL) {
212         snprintf(dlm->error, sizeof(dlm->error),
213                  "dlsym failed: can't find \'%s\'", sym_init);
214         dlm->status = DLMOD_ERROR;
215         return;
216     }
217
218     if (dl_init()) {
219         snprintf(dlm->error, sizeof(dlm->error), "\'%s\' failed",
220                  sym_init);
221         dlm->status = DLMOD_ERROR;
222         return;
223     }
224
225     dlm->error[0] = '\0';
226     dlm->status = DLMOD_LOADED;
227 }
228
229 void
230 dlmod_unload_module(struct dlmod *dlm)
231 {
232     char            sym_deinit[64];
233     char            buf[256];
234     int             (*dl_deinit) (void);
235
236     if (!dlm || dlm->status != DLMOD_LOADED)
237         return;
238
239     snprintf(sym_deinit, sizeof(sym_deinit), "_dynamic_deinit_%s",
240              dlm->name);
241     dl_deinit = dlsym(dlm->handle, sym_deinit);
242     if (dl_deinit == NULL) {
243         /** it's right way ? */
244         dlm->status = DLMOD_ERROR;
245         return;
246     }
247     dl_deinit();
248     dlclose(dlm->handle);
249     dlm->status = DLMOD_UNLOADED;
250 #if 1
251     DEBUGMSGTL(("dlmod", "Module %s unloaded\n", dlm->name));
252 #endif
253 }
254
255 int
256 dlmod_get_next_index(void)
257 {
258     return dlmod_next_index;
259 }
260
261 struct dlmod   *
262 dlmod_get_by_index(int iindex)
263 {
264     struct dlmod   *dlmod;
265
266     for (dlmod = dlmods; dlmod; dlmod = dlmod->next)
267         if (dlmod->index == iindex)
268             return dlmod;
269
270     return NULL;
271 }
272
273 #if 0
274 struct dlmod   *
275 dlmod_get_next(struct dlmod *dlm)
276 {
277     if (dlm)
278         return dlmods;
279     else
280         return dlm->next;
281 }
282 #endif