ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/modules.c
Revision: 2345
Committed: Wed Jul 3 18:17:39 2013 UTC (12 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 9076 byte(s)
Log Message:
- White-space commit / style corrections

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 michael 1237 #include "ltdl.h"
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #include "modules.h"
30 michael 1309 #include "log.h"
31 adx 30 #include "ircd.h"
32     #include "client.h"
33     #include "send.h"
34 michael 1309 #include "conf.h"
35 adx 30 #include "numeric.h"
36     #include "parse.h"
37     #include "ircd_defs.h"
38     #include "irc_string.h"
39     #include "memory.h"
40    
41    
42 michael 1447 dlink_list modules_list = { NULL, NULL, 0 };
43 adx 30
44 michael 1997 static dlink_list mod_paths = { NULL, NULL, 0 };
45     static dlink_list conf_modules = { NULL, NULL, 0 };
46    
47 michael 1237 static const char *unknown_ver = "<unknown>";
48 adx 30 static const char *core_module_table[] =
49     {
50 michael 912 "m_die.la",
51 michael 946 "m_error.la",
52 michael 912 "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 adx 30 NULL
64     };
65    
66 michael 1237 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 michael 1238 assert(dlink_list_length(&modules_list) > 0);
91     dlinkDelete(&modp->node, &modules_list);
92 michael 1237 MyFree(modp->name);
93    
94     lt_dlclose(modp->handle);
95    
96     if (warn == 1)
97     {
98 michael 1247 ilog(LOG_TYPE_IRCD, "Module %s unloaded", name);
99 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
100     "Module %s unloaded", name);
101 michael 1237 }
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 michael 1404 load_a_module(const char *path, int warn)
114 michael 1237 {
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     const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
124    
125 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
126     "Error loading module %s: %s",
127 michael 1237 mod_basename, err);
128 michael 1247 ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
129 michael 1237 return -1;
130     }
131    
132     if ((modp = lt_dlsym(tmpptr, "module_entry")) == NULL)
133     {
134 michael 1574 const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
135    
136 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
137     "Error loading module %s: %s",
138 michael 1574 mod_basename, err);
139     ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
140 michael 1237 lt_dlclose(tmpptr);
141     return -1;
142     }
143    
144     modp->handle = tmpptr;
145    
146     if (EmptyString(modp->version))
147     modp->version = unknown_ver;
148    
149 michael 1646 modp->name = xstrdup(mod_basename);
150 michael 1238 dlinkAdd(modp, &modp->node, &modules_list);
151 michael 1237
152     if (modp->modinit)
153     modp->modinit();
154    
155     if (warn == 1)
156     {
157 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
158 michael 1237 "Module %s [version: %s handle: %p] loaded.",
159     modp->name, modp->version, tmpptr);
160 michael 1247 ilog(LOG_TYPE_IRCD, "Module %s [version: %s handle: %p] loaded.",
161 michael 1237 modp->name, modp->version, tmpptr);
162     }
163    
164     return 0;
165     }
166    
167 adx 30 /*
168     * modules_init
169     *
170     * input - NONE
171     * output - NONE
172     * side effects - The basic module manipulation modules are loaded
173     */
174     void
175     modules_init(void)
176     {
177 michael 1237 if (lt_dlinit())
178     {
179 michael 1247 ilog(LOG_TYPE_IRCD, "Couldn't initialize the libltdl run time dynamic"
180 michael 1237 " link library. Exiting.");
181     exit(0);
182     }
183 adx 30 }
184    
185     /* mod_find_path()
186     *
187     * input - path
188     * output - none
189     * side effects - returns a module path from path
190     */
191     static struct module_path *
192     mod_find_path(const char *path)
193     {
194     dlink_node *ptr;
195    
196     DLINK_FOREACH(ptr, mod_paths.head)
197     {
198 michael 1404 struct module_path *mpath = ptr->data;
199 adx 30
200     if (!strcmp(path, mpath->path))
201     return mpath;
202     }
203    
204     return NULL;
205     }
206    
207     /* mod_add_path()
208     *
209     * input - path
210     * output - NONE
211     * side effects - adds path to list
212     */
213     void
214     mod_add_path(const char *path)
215     {
216     struct module_path *pathst;
217    
218     if (mod_find_path(path))
219     return;
220    
221     pathst = MyMalloc(sizeof(struct module_path));
222    
223     strlcpy(pathst->path, path, sizeof(pathst->path));
224     dlinkAdd(pathst, &pathst->node, &mod_paths);
225     }
226    
227     /* add_conf_module
228     *
229     * input - module name
230     * output - NONE
231     * side effects - adds module to conf_mod
232     */
233     void
234     add_conf_module(const char *name)
235     {
236     struct module_path *pathst;
237    
238     pathst = MyMalloc(sizeof(struct module_path));
239    
240     strlcpy(pathst->path, name, sizeof(pathst->path));
241     dlinkAdd(pathst, &pathst->node, &conf_modules);
242     }
243    
244     /* mod_clear_paths()
245     *
246     * input - NONE
247     * output - NONE
248     * side effects - clear the lists of paths and conf modules
249     */
250     void
251     mod_clear_paths(void)
252     {
253 michael 1237 dlink_node *ptr = NULL, *next_ptr = NULL;
254 adx 30
255     DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
256     {
257 michael 1404 dlinkDelete(ptr, &mod_paths);
258     MyFree(ptr->data);
259 adx 30 }
260    
261     DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
262     {
263 michael 1404 dlinkDelete(ptr, &conf_modules);
264     MyFree(ptr->data);
265 adx 30 }
266     }
267    
268     /* findmodule_byname
269     *
270     * input - name of module
271     * output - NULL if not found or pointer to module
272     * side effects - NONE
273     */
274 michael 1230 struct module *
275 adx 30 findmodule_byname(const char *name)
276     {
277 michael 1230 dlink_node *ptr = NULL;
278 adx 30
279 michael 1238 DLINK_FOREACH(ptr, modules_list.head)
280 adx 30 {
281 michael 1230 struct module *modp = ptr->data;
282 adx 30
283 db 218 if (strcmp(modp->name, name) == 0)
284 michael 1230 return modp;
285 adx 30 }
286    
287     return NULL;
288     }
289    
290     /* load_all_modules()
291     *
292     * input - int flag warn
293     * output - NONE
294     * side effects - load all modules found in autoload directory
295     */
296     void
297     load_all_modules(int warn)
298     {
299     DIR *system_module_dir = NULL;
300     struct dirent *ldirent = NULL;
301 michael 1737 char module_fq_name[HYB_PATH_MAX + 1];
302 adx 30
303     if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
304     {
305 michael 1247 ilog(LOG_TYPE_IRCD, "Could not load modules from %s: %s",
306 adx 30 AUTOMODPATH, strerror(errno));
307     return;
308     }
309    
310     while ((ldirent = readdir(system_module_dir)) != NULL)
311     {
312 michael 912 if (modules_valid_suffix(ldirent->d_name))
313 adx 30 {
314     snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
315     AUTOMODPATH, ldirent->d_name);
316 michael 1404 load_a_module(module_fq_name, warn);
317 adx 30 }
318     }
319    
320     closedir(system_module_dir);
321     }
322    
323     /* load_conf_modules()
324     *
325     * input - NONE
326     * output - NONE
327     * side effects - load modules given in ircd.conf
328     */
329     void
330     load_conf_modules(void)
331     {
332     dlink_node *ptr = NULL;
333    
334     DLINK_FOREACH(ptr, conf_modules.head)
335     {
336 michael 1404 struct module_path *mpath = ptr->data;
337 adx 30
338     if (findmodule_byname(mpath->path) == NULL)
339 michael 1404 load_one_module(mpath->path);
340 adx 30 }
341     }
342    
343     /* load_core_modules()
344     *
345     * input - int flag warn
346     * output - NONE
347     * side effects - core modules are loaded, if any fail, kill ircd
348     */
349     void
350     load_core_modules(int warn)
351     {
352 michael 1737 char module_name[HYB_PATH_MAX + 1];
353 adx 30 int i = 0;
354    
355     for (; core_module_table[i]; ++i)
356     {
357 michael 912 snprintf(module_name, sizeof(module_name), "%s%s",
358     MODPATH, core_module_table[i]);
359 adx 30
360 michael 1404 if (load_a_module(module_name, warn) == -1)
361 adx 30 {
362 michael 1247 ilog(LOG_TYPE_IRCD, "Error loading core module %s: terminating ircd",
363 michael 912 core_module_table[i]);
364 adx 30 exit(EXIT_FAILURE);
365     }
366     }
367     }
368    
369     /* load_one_module()
370     *
371     * input - pointer to path
372     * - flagged as core module or not
373 michael 2345 * output - -1 if error
374 adx 30 * side effects - module is loaded if found.
375     */
376     int
377 michael 1404 load_one_module(const char *path)
378 adx 30 {
379     dlink_node *ptr = NULL;
380 michael 1737 char modpath[HYB_PATH_MAX + 1];
381 adx 30 struct stat statbuf;
382    
383     DLINK_FOREACH(ptr, mod_paths.head)
384     {
385     const struct module_path *mpath = ptr->data;
386    
387     snprintf(modpath, sizeof(modpath), "%s/%s", mpath->path, path);
388    
389 michael 912 if (!modules_valid_suffix(path))
390     continue;
391    
392 adx 30 if (strstr(modpath, "../") == NULL &&
393 michael 2345 strstr(modpath, "/..") == NULL)
394 adx 30 if (!stat(modpath, &statbuf))
395 michael 1404 if (S_ISREG(statbuf.st_mode)) /* Regular files only please */
396     return load_a_module(modpath, 1);
397 adx 30 }
398    
399 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
400 adx 30 "Cannot locate module %s", path);
401 michael 1247 ilog(LOG_TYPE_IRCD, "Cannot locate module %s", path);
402 adx 30 return -1;
403     }

Properties

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