ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/modules.c
Revision: 2525
Committed: Sat Nov 2 17:07:38 2013 UTC (10 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/modules.c
File size: 9078 byte(s)
Log Message:
- Style corrections

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * modules.c: A module loader.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "ltdl.h"
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "modules.h"
30 #include "log.h"
31 #include "ircd.h"
32 #include "client.h"
33 #include "send.h"
34 #include "conf.h"
35 #include "numeric.h"
36 #include "parse.h"
37 #include "ircd_defs.h"
38 #include "irc_string.h"
39 #include "memory.h"
40
41
42 dlink_list modules_list = { NULL, NULL, 0 };
43
44 static dlink_list mod_paths = { NULL, NULL, 0 };
45 static dlink_list conf_modules = { NULL, NULL, 0 };
46
47 static const char *unknown_ver = "<unknown>";
48 static const char *core_module_table[] =
49 {
50 "m_die.la",
51 "m_error.la",
52 "m_join.la",
53 "m_kick.la",
54 "m_kill.la",
55 "m_message.la",
56 "m_mode.la",
57 "m_nick.la",
58 "m_part.la",
59 "m_quit.la",
60 "m_server.la",
61 "m_sjoin.la",
62 "m_squit.la",
63 NULL
64 };
65
66 int
67 modules_valid_suffix(const char *name)
68 {
69 return ((name = strrchr(name, '.'))) && !strcmp(name, ".la");
70 }
71
72 /* unload_one_module()
73 *
74 * inputs - name of module to unload
75 * - 1 to say modules unloaded, 0 to not
76 * output - 0 if successful, -1 if error
77 * side effects - module is unloaded
78 */
79 int
80 unload_one_module(const char *name, int warn)
81 {
82 struct module *modp = NULL;
83
84 if ((modp = findmodule_byname(name)) == NULL)
85 return -1;
86
87 if (modp->modexit)
88 modp->modexit();
89
90 assert(dlink_list_length(&modules_list) > 0);
91 dlinkDelete(&modp->node, &modules_list);
92 MyFree(modp->name);
93
94 lt_dlclose(modp->handle);
95
96 if (warn == 1)
97 {
98 ilog(LOG_TYPE_IRCD, "Module %s unloaded", name);
99 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
100 "Module %s unloaded", name);
101 }
102
103 return 0;
104 }
105
106 /* load_a_module()
107 *
108 * inputs - path name of module, int to notice, int of core
109 * output - -1 if error 0 if success
110 * side effects - loads a module if successful
111 */
112 int
113 load_a_module(const char *path, int warn)
114 {
115 lt_dlhandle tmpptr = NULL;
116 const char *mod_basename = NULL;
117 struct module *modp = NULL;
118
119 if (findmodule_byname((mod_basename = libio_basename(path))))
120 return 1;
121
122 if (!(tmpptr = lt_dlopen(path)))
123 {
124 const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
125
126 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
127 "Error loading module %s: %s",
128 mod_basename, err);
129 ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
130 return -1;
131 }
132
133 if ((modp = lt_dlsym(tmpptr, "module_entry")) == NULL)
134 {
135 const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
136
137 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
138 "Error loading module %s: %s",
139 mod_basename, err);
140 ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
141 lt_dlclose(tmpptr);
142 return -1;
143 }
144
145 modp->handle = tmpptr;
146
147 if (EmptyString(modp->version))
148 modp->version = unknown_ver;
149
150 modp->name = xstrdup(mod_basename);
151 dlinkAdd(modp, &modp->node, &modules_list);
152
153 if (modp->modinit)
154 modp->modinit();
155
156 if (warn == 1)
157 {
158 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
159 "Module %s [version: %s handle: %p] loaded.",
160 modp->name, modp->version, tmpptr);
161 ilog(LOG_TYPE_IRCD, "Module %s [version: %s handle: %p] loaded.",
162 modp->name, modp->version, tmpptr);
163 }
164
165 return 0;
166 }
167
168 /*
169 * modules_init
170 *
171 * input - NONE
172 * output - NONE
173 * side effects - The basic module manipulation modules are loaded
174 */
175 void
176 modules_init(void)
177 {
178 if (lt_dlinit())
179 {
180 ilog(LOG_TYPE_IRCD, "Couldn't initialize the libltdl run time dynamic"
181 " link library. Exiting.");
182 exit(0);
183 }
184 }
185
186 /* mod_find_path()
187 *
188 * input - path
189 * output - none
190 * side effects - returns a module path from path
191 */
192 static struct module_path *
193 mod_find_path(const char *path)
194 {
195 dlink_node *ptr;
196
197 DLINK_FOREACH(ptr, mod_paths.head)
198 {
199 struct module_path *mpath = ptr->data;
200
201 if (!strcmp(path, mpath->path))
202 return mpath;
203 }
204
205 return NULL;
206 }
207
208 /* mod_add_path()
209 *
210 * input - path
211 * output - NONE
212 * side effects - adds path to list
213 */
214 void
215 mod_add_path(const char *path)
216 {
217 struct module_path *pathst;
218
219 if (mod_find_path(path))
220 return;
221
222 pathst = MyMalloc(sizeof(struct module_path));
223
224 strlcpy(pathst->path, path, sizeof(pathst->path));
225 dlinkAdd(pathst, &pathst->node, &mod_paths);
226 }
227
228 /* add_conf_module
229 *
230 * input - module name
231 * output - NONE
232 * side effects - adds module to conf_mod
233 */
234 void
235 add_conf_module(const char *name)
236 {
237 struct module_path *pathst;
238
239 pathst = MyMalloc(sizeof(struct module_path));
240
241 strlcpy(pathst->path, name, sizeof(pathst->path));
242 dlinkAdd(pathst, &pathst->node, &conf_modules);
243 }
244
245 /* mod_clear_paths()
246 *
247 * input - NONE
248 * output - NONE
249 * side effects - clear the lists of paths and conf modules
250 */
251 void
252 mod_clear_paths(void)
253 {
254 dlink_node *ptr = NULL, *next_ptr = NULL;
255
256 DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
257 {
258 dlinkDelete(ptr, &mod_paths);
259 MyFree(ptr->data);
260 }
261
262 DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
263 {
264 dlinkDelete(ptr, &conf_modules);
265 MyFree(ptr->data);
266 }
267 }
268
269 /* findmodule_byname
270 *
271 * input - name of module
272 * output - NULL if not found or pointer to module
273 * side effects - NONE
274 */
275 struct module *
276 findmodule_byname(const char *name)
277 {
278 dlink_node *ptr = NULL;
279
280 DLINK_FOREACH(ptr, modules_list.head)
281 {
282 struct module *modp = ptr->data;
283
284 if (strcmp(modp->name, name) == 0)
285 return modp;
286 }
287
288 return NULL;
289 }
290
291 /* load_all_modules()
292 *
293 * input - int flag warn
294 * output - NONE
295 * side effects - load all modules found in autoload directory
296 */
297 void
298 load_all_modules(int warn)
299 {
300 DIR *system_module_dir = NULL;
301 struct dirent *ldirent = NULL;
302 char module_fq_name[HYB_PATH_MAX + 1];
303
304 if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
305 {
306 ilog(LOG_TYPE_IRCD, "Could not load modules from %s: %s",
307 AUTOMODPATH, strerror(errno));
308 return;
309 }
310
311 while ((ldirent = readdir(system_module_dir)) != NULL)
312 {
313 if (modules_valid_suffix(ldirent->d_name))
314 {
315 snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
316 AUTOMODPATH, ldirent->d_name);
317 load_a_module(module_fq_name, warn);
318 }
319 }
320
321 closedir(system_module_dir);
322 }
323
324 /* load_conf_modules()
325 *
326 * input - NONE
327 * output - NONE
328 * side effects - load modules given in ircd.conf
329 */
330 void
331 load_conf_modules(void)
332 {
333 dlink_node *ptr = NULL;
334
335 DLINK_FOREACH(ptr, conf_modules.head)
336 {
337 struct module_path *mpath = ptr->data;
338
339 if (findmodule_byname(mpath->path) == NULL)
340 load_one_module(mpath->path);
341 }
342 }
343
344 /* load_core_modules()
345 *
346 * input - int flag warn
347 * output - NONE
348 * side effects - core modules are loaded, if any fail, kill ircd
349 */
350 void
351 load_core_modules(int warn)
352 {
353 char module_name[HYB_PATH_MAX + 1];
354 int i = 0;
355
356 for (; core_module_table[i]; ++i)
357 {
358 snprintf(module_name, sizeof(module_name), "%s%s",
359 MODPATH, core_module_table[i]);
360
361 if (load_a_module(module_name, warn) == -1)
362 {
363 ilog(LOG_TYPE_IRCD, "Error loading core module %s: terminating ircd",
364 core_module_table[i]);
365 exit(EXIT_FAILURE);
366 }
367 }
368 }
369
370 /* load_one_module()
371 *
372 * input - pointer to path
373 * - flagged as core module or not
374 * output - -1 if error
375 * side effects - module is loaded if found.
376 */
377 int
378 load_one_module(const char *path)
379 {
380 dlink_node *ptr = NULL;
381 char modpath[HYB_PATH_MAX + 1];
382 struct stat statbuf;
383
384 DLINK_FOREACH(ptr, mod_paths.head)
385 {
386 const struct module_path *mpath = ptr->data;
387
388 snprintf(modpath, sizeof(modpath), "%s/%s", mpath->path, path);
389
390 if (!modules_valid_suffix(path))
391 continue;
392
393 if (strstr(modpath, "../") == NULL &&
394 strstr(modpath, "/..") == NULL)
395 if (!stat(modpath, &statbuf))
396 if (S_ISREG(statbuf.st_mode)) /* Regular files only please */
397 return load_a_module(modpath, 1);
398 }
399
400 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
401 "Cannot locate module %s", path);
402 ilog(LOG_TYPE_IRCD, "Cannot locate module %s", path);
403 return -1;
404 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision