ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/modules.c
Revision: 912
Committed: Wed Nov 7 22:47:44 2007 UTC (18 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/modules.c
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

# User Rev Content
1 adx 30 /*
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 knight 31 * $Id$
23 adx 30 */
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 michael 912 "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 adx 30 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 michael 912 dynlink_init();
119    
120 adx 30 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 db 218 if (strcmp(modp->name, name) == 0)
235 adx 30 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 michael 912 if (modules_valid_suffix(ldirent->d_name))
266 adx 30 {
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 michael 912 snprintf(module_name, sizeof(module_name), "%s%s",
312     MODPATH, core_module_table[i]);
313 adx 30
314     if (load_a_module(module_name, warn, 1) == -1)
315     {
316 michael 912 ilog(L_CRIT, "Error loading core module %s: terminating ircd",
317     core_module_table[i]);
318 adx 30 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 michael 912 if (!modules_valid_suffix(path))
344     continue;
345    
346 adx 30 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 michael 912 const dlink_node *ptr = NULL;
487 adx 30
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 michael 912 const struct module *modp = ptr->data;
498 adx 30
499 michael 912 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 adx 30 }
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 michael 912 dlink_node *ptr = NULL, *ptr_next = NULL;
518    
519 adx 30 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 michael 912 DLINK_FOREACH_SAFE(ptr, ptr_next, mod_list.head)
532 adx 30 {
533 michael 912 struct module *modp = ptr->data;
534 adx 30 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