/[svn]/ircd-hybrid/branches/8.2.x/src/modules.c
ViewVC logotype

Contents of /ircd-hybrid/branches/8.2.x/src/modules.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6554 - (show annotations)
Sat Oct 3 16:56:36 2015 UTC (4 years, 11 months ago) by michael
File MIME type: text/x-chdr
File size: 9226 byte(s)
- Use EXIT_FAILURE in some places instead of hardcoded values

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

Properties

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

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