/[svn]/ircd-hybrid-7.2/src/modules.c
ViewVC logotype

Contents of /ircd-hybrid-7.2/src/modules.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1013 - (show annotations)
Sun Oct 18 14:26:49 2009 UTC (10 years ago) by michael
File MIME type: text/x-chdr
File size: 12160 byte(s)
- Add -Wextra -Wcast-align -Wbad-function-cast to CFLAGS if --enable-warnings is specified
- Fixed several compile warnings
- 64-bit cleanliness fixes, e.g., reorganize data structures to reduce storage/unnecessary padding

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 "stdinc.h"
26 #include "list.h"
27 #include "modules.h"
28 #include "s_log.h"
29 #include "ircd.h"
30 #include "client.h"
31 #include "send.h"
32 #include "s_conf.h"
33 #include "handlers.h"
34 #include "numeric.h"
35 #include "parse.h"
36 #include "ircd_defs.h"
37 #include "irc_string.h"
38 #include "memory.h"
39
40
41 dlink_list mod_list = { NULL, NULL, 0 };
42
43 static const char *core_module_table[] =
44 {
45 "m_die.la",
46 "m_error.la",
47 "m_join.la",
48 "m_kick.la",
49 "m_kill.la",
50 "m_message.la",
51 "m_mode.la",
52 "m_nick.la",
53 "m_part.la",
54 "m_quit.la",
55 "m_server.la",
56 "m_sjoin.la",
57 "m_squit.la",
58 NULL
59 };
60
61 static dlink_list mod_paths = { NULL, NULL, 0 };
62 static dlink_list conf_modules = { NULL, NULL, 0 };
63
64 static void mo_modload(struct Client *, struct Client *, int, char *[]);
65 static void mo_modlist(struct Client *, struct Client *, int, char *[]);
66 static void mo_modreload(struct Client *, struct Client *, int, char *[]);
67 static void mo_modunload(struct Client *, struct Client *, int, char *[]);
68 static void mo_modrestart(struct Client *, struct Client *, int, char *[]);
69
70 struct Message modload_msgtab = {
71 "MODLOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
72 {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modload, m_ignore}
73 };
74
75 struct Message modunload_msgtab = {
76 "MODUNLOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
77 {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modunload, m_ignore}
78 };
79
80 struct Message modreload_msgtab = {
81 "MODRELOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
82 {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modreload, m_ignore}
83 };
84
85 struct Message modlist_msgtab = {
86 "MODLIST", 0, 0, 0, 0, MFLG_SLOW, 0,
87 {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modlist, m_ignore}
88 };
89
90 struct Message modrestart_msgtab = {
91 "MODRESTART", 0, 0, 0, 0, MFLG_SLOW, 0,
92 {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modrestart, m_ignore}
93 };
94
95
96 /*
97 * modules_init
98 *
99 * input - NONE
100 * output - NONE
101 * side effects - The basic module manipulation modules are loaded
102 */
103 void
104 modules_init(void)
105 {
106 dynlink_init();
107
108 mod_add_cmd(&modload_msgtab);
109 mod_add_cmd(&modunload_msgtab);
110 mod_add_cmd(&modreload_msgtab);
111 mod_add_cmd(&modlist_msgtab);
112 mod_add_cmd(&modrestart_msgtab);
113 }
114
115 /* mod_find_path()
116 *
117 * input - path
118 * output - none
119 * side effects - returns a module path from path
120 */
121 static struct module_path *
122 mod_find_path(const char *path)
123 {
124 dlink_node *ptr;
125 struct module_path *mpath;
126
127 DLINK_FOREACH(ptr, mod_paths.head)
128 {
129 mpath = ptr->data;
130
131 if (!strcmp(path, mpath->path))
132 return mpath;
133 }
134
135 return NULL;
136 }
137
138 /* mod_add_path()
139 *
140 * input - path
141 * output - NONE
142 * side effects - adds path to list
143 */
144 void
145 mod_add_path(const char *path)
146 {
147 struct module_path *pathst;
148
149 if (mod_find_path(path))
150 return;
151
152 pathst = MyMalloc(sizeof(struct module_path));
153
154 strlcpy(pathst->path, path, sizeof(pathst->path));
155 dlinkAdd(pathst, &pathst->node, &mod_paths);
156 }
157
158 /* add_conf_module
159 *
160 * input - module name
161 * output - NONE
162 * side effects - adds module to conf_mod
163 */
164 void
165 add_conf_module(const char *name)
166 {
167 struct module_path *pathst;
168
169 pathst = MyMalloc(sizeof(struct module_path));
170
171 strlcpy(pathst->path, name, sizeof(pathst->path));
172 dlinkAdd(pathst, &pathst->node, &conf_modules);
173 }
174
175 /* mod_clear_paths()
176 *
177 * input - NONE
178 * output - NONE
179 * side effects - clear the lists of paths and conf modules
180 */
181 void
182 mod_clear_paths(void)
183 {
184 struct module_path *pathst;
185 dlink_node *ptr;
186 dlink_node *next_ptr;
187
188 DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
189 {
190 pathst = ptr->data;
191
192 dlinkDelete(&pathst->node, &mod_paths);
193 MyFree(pathst);
194 }
195
196 DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
197 {
198 pathst = ptr->data;
199
200 dlinkDelete(&pathst->node, &conf_modules);
201 MyFree(pathst);
202 }
203 }
204
205 /* findmodule_byname
206 *
207 * input - name of module
208 * output - NULL if not found or pointer to module
209 * side effects - NONE
210 */
211 dlink_node *
212 findmodule_byname(const char *name)
213 {
214 dlink_node *ptr;
215 struct module *modp;
216
217 DLINK_FOREACH(ptr, mod_list.head)
218 {
219 modp = ptr->data;
220
221 if (strcmp(modp->name, name) == 0)
222 return ptr;
223 }
224
225 return NULL;
226 }
227
228 /* load_all_modules()
229 *
230 * input - int flag warn
231 * output - NONE
232 * side effects - load all modules found in autoload directory
233 */
234 void
235 load_all_modules(int warn)
236 {
237 DIR *system_module_dir = NULL;
238 struct dirent *ldirent = NULL;
239 char module_fq_name[PATH_MAX + 1];
240
241 modules_init();
242
243 if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
244 {
245 ilog(L_WARN, "Could not load modules from %s: %s",
246 AUTOMODPATH, strerror(errno));
247 return;
248 }
249
250 while ((ldirent = readdir(system_module_dir)) != NULL)
251 {
252 if (modules_valid_suffix(ldirent->d_name))
253 {
254 snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
255 AUTOMODPATH, ldirent->d_name);
256 load_a_module(module_fq_name, warn, 0);
257 }
258 }
259
260 closedir(system_module_dir);
261 }
262
263 /* load_conf_modules()
264 *
265 * input - NONE
266 * output - NONE
267 * side effects - load modules given in ircd.conf
268 */
269 void
270 load_conf_modules(void)
271 {
272 dlink_node *ptr = NULL;
273 struct module_path *mpath = NULL;
274
275 DLINK_FOREACH(ptr, conf_modules.head)
276 {
277 mpath = ptr->data;
278
279 if (findmodule_byname(mpath->path) == NULL)
280 load_one_module(mpath->path, 0);
281 }
282 }
283
284 /* load_core_modules()
285 *
286 * input - int flag warn
287 * output - NONE
288 * side effects - core modules are loaded, if any fail, kill ircd
289 */
290 void
291 load_core_modules(int warn)
292 {
293 char module_name[PATH_MAX + 1];
294 int i = 0;
295
296 for (; core_module_table[i]; ++i)
297 {
298 snprintf(module_name, sizeof(module_name), "%s%s",
299 MODPATH, core_module_table[i]);
300
301 if (load_a_module(module_name, warn, 1) == -1)
302 {
303 ilog(L_CRIT, "Error loading core module %s: terminating ircd",
304 core_module_table[i]);
305 exit(EXIT_FAILURE);
306 }
307 }
308 }
309
310 /* load_one_module()
311 *
312 * input - pointer to path
313 * - flagged as core module or not
314 * output - -1 if error
315 * side effects - module is loaded if found.
316 */
317 int
318 load_one_module(const char *path, int coremodule)
319 {
320 dlink_node *ptr = NULL;
321 char modpath[PATH_MAX + 1];
322 struct stat statbuf;
323
324 DLINK_FOREACH(ptr, mod_paths.head)
325 {
326 const struct module_path *mpath = ptr->data;
327
328 snprintf(modpath, sizeof(modpath), "%s/%s", mpath->path, path);
329
330 if (!modules_valid_suffix(path))
331 continue;
332
333 if (strstr(modpath, "../") == NULL &&
334 strstr(modpath, "/..") == NULL)
335 {
336 if (!stat(modpath, &statbuf))
337 {
338 if (S_ISREG(statbuf.st_mode))
339 {
340 /* Regular files only please */
341 return load_a_module(modpath, 1, coremodule);
342 }
343 }
344 }
345 }
346
347 sendto_realops_flags(UMODE_ALL, L_ALL,
348 "Cannot locate module %s", path);
349 ilog(L_WARN, "Cannot locate module %s", path);
350 return -1;
351 }
352
353 /* load a module .. */
354 static void
355 mo_modload(struct Client *client_p, struct Client *source_p,
356 int parc, char *parv[])
357 {
358 const char *m_bn = NULL;
359
360 if (!IsAdmin(source_p))
361 {
362 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
363 me.name, source_p->name);
364 return;
365 }
366
367 m_bn = libio_basename(parv[1]);
368
369 if (findmodule_byname(m_bn) != NULL)
370 {
371 sendto_one(source_p, ":%s NOTICE %s :Module %s is already loaded",
372 me.name, source_p->name, m_bn);
373 return;
374 }
375
376 load_one_module(parv[1], 0);
377 }
378
379 /* unload a module .. */
380 static void
381 mo_modunload(struct Client *client_p, struct Client *source_p,
382 int parc, char *parv[])
383 {
384 const char *m_bn = NULL;
385 dlink_node *ptr;
386 struct module *modp;
387
388 if (!IsAdmin(source_p))
389 {
390 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
391 me.name, source_p->name);
392 return;
393 }
394
395 m_bn = libio_basename(parv[1]);
396
397 if ((ptr = findmodule_byname(m_bn)) == NULL)
398 {
399 sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
400 me.name, source_p->name, m_bn);
401 return;
402 }
403
404 modp = ptr->data;
405
406 if (modp->core == 1)
407 {
408 sendto_one(source_p,
409 ":%s NOTICE %s :Module %s is a core module and may not be unloaded",
410 me.name, source_p->name, m_bn);
411 return;
412 }
413
414 /* XXX might want to simply un dlink it here */
415
416 if (unload_one_module(m_bn, 1) == -1)
417 {
418 sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
419 me.name, source_p->name, m_bn);
420 }
421 }
422
423 /* unload and load in one! */
424 static void
425 mo_modreload(struct Client *client_p, struct Client *source_p,
426 int parc, char *parv[])
427 {
428 const char *m_bn = NULL;
429 dlink_node *ptr;
430 struct module *modp;
431 int check_core;
432
433 if (!IsAdmin(source_p))
434 {
435 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
436 me.name, source_p->name);
437 return;
438 }
439
440 m_bn = libio_basename(parv[1]);
441
442 if ((ptr = findmodule_byname(m_bn)) == NULL)
443 {
444 sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
445 me.name, source_p->name, m_bn);
446 return;
447 }
448
449 modp = ptr->data;
450 check_core = modp->core;
451
452 if (unload_one_module(m_bn, 1) == -1)
453 {
454 sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
455 me.name, source_p->name, m_bn);
456 return;
457 }
458
459 if ((load_one_module(parv[1], check_core) == -1) && check_core)
460 {
461 sendto_realops_flags(UMODE_ALL, L_ALL, "Error reloading core "
462 "module: %s: terminating ircd", parv[1]);
463 ilog(L_CRIT, "Error loading core module %s: terminating ircd", parv[1]);
464 exit(0);
465 }
466 }
467
468 /* list modules .. */
469 static void
470 mo_modlist(struct Client *client_p, struct Client *source_p,
471 int parc, char *parv[])
472 {
473 const dlink_node *ptr = NULL;
474
475 if (!IsAdmin(source_p))
476 {
477 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
478 me.name, source_p->name);
479 return;
480 }
481
482 DLINK_FOREACH(ptr, mod_list.head)
483 {
484 const struct module *modp = ptr->data;
485
486 if (parc > 1 && !match(parv[1], modp->name))
487 continue;
488
489 sendto_one(source_p, form_str(RPL_MODLIST), me.name, parv[0],
490 modp->name, modp->handle,
491 modp->version, modp->core?"(core)":"");
492 }
493
494 sendto_one(source_p, form_str(RPL_ENDOFMODLIST),
495 me.name, source_p->name);
496 }
497
498 /* unload and reload all modules */
499 static void
500 mo_modrestart(struct Client *client_p, struct Client *source_p,
501 int parc, char *parv[])
502 {
503 unsigned int modnum = 0;
504 dlink_node *ptr = NULL, *ptr_next = NULL;
505
506 if (!IsAdmin(source_p))
507 {
508 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
509 me.name, source_p->name);
510 return;
511 }
512
513 sendto_one(source_p, ":%s NOTICE %s :Reloading all modules",
514 me.name, source_p->name);
515
516 modnum = dlink_list_length(&mod_list);
517
518 DLINK_FOREACH_SAFE(ptr, ptr_next, mod_list.head)
519 {
520 struct module *modp = ptr->data;
521 unload_one_module(modp->name, 0);
522 }
523
524 load_all_modules(0);
525 load_conf_modules();
526 load_core_modules(0);
527
528 sendto_realops_flags(UMODE_ALL, L_ALL,
529 "Module Restart: %u modules unloaded, %u modules loaded",
530 modnum, dlink_list_length(&mod_list));
531 ilog(L_WARN, "Module Restart: %u modules unloaded, %u modules loaded",
532 modnum, dlink_list_length(&mod_list));
533 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.26