ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/modules.c
Revision: 912
Committed: Wed Nov 7 22:47:44 2007 UTC (16 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 12535 byte(s)
Log Message:
- Implemented libtool-ltdl. Only shared modules are supported currently
- Several build fixes and cleanups. ircd now builds and runs without any problems
- Added back all files to SVN that are needed to built the daemon
  I really don't want to force other people that want to test the snapshots
  or svn versions to install yyacc, lex, automake, autoconf and libtool...
  No problem having required files in svn
- Removed some automake maintainer stuff which is kinda useless for us

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

Properties

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