ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/modules.c
Revision: 2916
Committed: Sat Jan 25 21:09:18 2014 UTC (11 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 9101 byte(s)
Log Message:
- Clean up all files in include/ (fixed indentation, removed whitespaces/tabs)
- Fixed copyright years

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 2000-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
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 dlink_list modules_list = { NULL, NULL, 0 };
45
46 static dlink_list mod_paths = { NULL, NULL, 0 };
47 static dlink_list conf_modules = { NULL, NULL, 0 };
48
49 static const char *unknown_ver = "<unknown>";
50 static const char *core_module_table[] =
51 {
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 NULL
66 };
67
68 int
69 modules_valid_suffix(const char *name)
70 {
71 return ((name = strrchr(name, '.'))) && !strcmp(name, ".la");
72 }
73
74 /* unload_one_module()
75 *
76 * inputs - name of module to unload
77 * - 1 to say modules unloaded, 0 to not
78 * output - 0 if successful, -1 if error
79 * side effects - module is unloaded
80 */
81 int
82 unload_one_module(const char *name, int warn)
83 {
84 struct module *modp = NULL;
85
86 if ((modp = findmodule_byname(name)) == NULL)
87 return -1;
88
89 if (modp->modexit)
90 modp->modexit();
91
92 assert(dlink_list_length(&modules_list) > 0);
93 dlinkDelete(&modp->node, &modules_list);
94 MyFree(modp->name);
95
96 lt_dlclose(modp->handle);
97
98 if (warn == 1)
99 {
100 ilog(LOG_TYPE_IRCD, "Module %s unloaded", name);
101 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
102 "Module %s unloaded", name);
103 }
104
105 return 0;
106 }
107
108 /* load_a_module()
109 *
110 * inputs - path name of module, int to notice, int of core
111 * output - -1 if error 0 if success
112 * side effects - loads a module if successful
113 */
114 int
115 load_a_module(const char *path, int warn)
116 {
117 lt_dlhandle tmpptr = NULL;
118 const char *mod_basename = NULL;
119 struct module *modp = NULL;
120
121 if (findmodule_byname((mod_basename = libio_basename(path))))
122 return 1;
123
124 if (!(tmpptr = lt_dlopen(path)))
125 {
126 const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
127
128 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
129 "Error loading module %s: %s",
130 mod_basename, err);
131 ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
132 return -1;
133 }
134
135 if ((modp = lt_dlsym(tmpptr, "module_entry")) == NULL)
136 {
137 const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
138
139 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
140 "Error loading module %s: %s",
141 mod_basename, err);
142 ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
143 lt_dlclose(tmpptr);
144 return -1;
145 }
146
147 modp->handle = tmpptr;
148
149 if (EmptyString(modp->version))
150 modp->version = unknown_ver;
151
152 modp->name = xstrdup(mod_basename);
153 dlinkAdd(modp, &modp->node, &modules_list);
154
155 if (modp->modinit)
156 modp->modinit();
157
158 if (warn == 1)
159 {
160 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
161 "Module %s [version: %s handle: %p] loaded.",
162 modp->name, modp->version, tmpptr);
163 ilog(LOG_TYPE_IRCD, "Module %s [version: %s handle: %p] loaded.",
164 modp->name, modp->version, tmpptr);
165 }
166
167 return 0;
168 }
169
170 /*
171 * modules_init
172 *
173 * input - NONE
174 * output - NONE
175 * side effects - The basic module manipulation modules are loaded
176 */
177 void
178 modules_init(void)
179 {
180 if (lt_dlinit())
181 {
182 ilog(LOG_TYPE_IRCD, "Couldn't initialize the libltdl run time dynamic"
183 " link library. Exiting.");
184 exit(0);
185 }
186 }
187
188 /* mod_find_path()
189 *
190 * input - path
191 * output - none
192 * side effects - returns a module path from path
193 */
194 static struct module_path *
195 mod_find_path(const char *path)
196 {
197 dlink_node *ptr;
198
199 DLINK_FOREACH(ptr, mod_paths.head)
200 {
201 struct module_path *mpath = ptr->data;
202
203 if (!strcmp(path, mpath->path))
204 return mpath;
205 }
206
207 return NULL;
208 }
209
210 /* mod_add_path()
211 *
212 * input - path
213 * output - NONE
214 * side effects - adds path to list
215 */
216 void
217 mod_add_path(const char *path)
218 {
219 struct module_path *pathst;
220
221 if (mod_find_path(path))
222 return;
223
224 pathst = MyMalloc(sizeof(struct module_path));
225
226 strlcpy(pathst->path, path, sizeof(pathst->path));
227 dlinkAdd(pathst, &pathst->node, &mod_paths);
228 }
229
230 /* add_conf_module
231 *
232 * input - module name
233 * output - NONE
234 * side effects - adds module to conf_mod
235 */
236 void
237 add_conf_module(const char *name)
238 {
239 struct module_path *pathst;
240
241 pathst = MyMalloc(sizeof(struct module_path));
242
243 strlcpy(pathst->path, name, sizeof(pathst->path));
244 dlinkAdd(pathst, &pathst->node, &conf_modules);
245 }
246
247 /* mod_clear_paths()
248 *
249 * input - NONE
250 * output - NONE
251 * side effects - clear the lists of paths and conf modules
252 */
253 void
254 mod_clear_paths(void)
255 {
256 dlink_node *ptr = NULL, *next_ptr = NULL;
257
258 DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
259 {
260 dlinkDelete(ptr, &mod_paths);
261 MyFree(ptr->data);
262 }
263
264 DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
265 {
266 dlinkDelete(ptr, &conf_modules);
267 MyFree(ptr->data);
268 }
269 }
270
271 /* findmodule_byname
272 *
273 * input - name of module
274 * output - NULL if not found or pointer to module
275 * side effects - NONE
276 */
277 struct module *
278 findmodule_byname(const char *name)
279 {
280 dlink_node *ptr = NULL;
281
282 DLINK_FOREACH(ptr, modules_list.head)
283 {
284 struct module *modp = ptr->data;
285
286 if (strcmp(modp->name, name) == 0)
287 return modp;
288 }
289
290 return NULL;
291 }
292
293 /* load_all_modules()
294 *
295 * input - int flag warn
296 * output - NONE
297 * side effects - load all modules found in autoload directory
298 */
299 void
300 load_all_modules(int warn)
301 {
302 DIR *system_module_dir = NULL;
303 struct dirent *ldirent = NULL;
304 char module_fq_name[HYB_PATH_MAX + 1];
305
306 if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
307 {
308 ilog(LOG_TYPE_IRCD, "Could not load modules from %s: %s",
309 AUTOMODPATH, strerror(errno));
310 return;
311 }
312
313 while ((ldirent = readdir(system_module_dir)) != NULL)
314 {
315 if (modules_valid_suffix(ldirent->d_name))
316 {
317 snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
318 AUTOMODPATH, ldirent->d_name);
319 load_a_module(module_fq_name, warn);
320 }
321 }
322
323 closedir(system_module_dir);
324 }
325
326 /* load_conf_modules()
327 *
328 * input - NONE
329 * output - NONE
330 * side effects - load modules given in ircd.conf
331 */
332 void
333 load_conf_modules(void)
334 {
335 dlink_node *ptr = NULL;
336
337 DLINK_FOREACH(ptr, conf_modules.head)
338 {
339 struct module_path *mpath = ptr->data;
340
341 if (findmodule_byname(mpath->path) == NULL)
342 load_one_module(mpath->path);
343 }
344 }
345
346 /* load_core_modules()
347 *
348 * input - int flag warn
349 * output - NONE
350 * side effects - core modules are loaded, if any fail, kill ircd
351 */
352 void
353 load_core_modules(int warn)
354 {
355 char module_name[HYB_PATH_MAX + 1];
356 int i = 0;
357
358 for (; core_module_table[i]; ++i)
359 {
360 snprintf(module_name, sizeof(module_name), "%s%s",
361 MODPATH, core_module_table[i]);
362
363 if (load_a_module(module_name, warn) == -1)
364 {
365 ilog(LOG_TYPE_IRCD, "Error loading core module %s: terminating ircd",
366 core_module_table[i]);
367 exit(EXIT_FAILURE);
368 }
369 }
370 }
371
372 /* load_one_module()
373 *
374 * input - pointer to path
375 * - flagged as core module or not
376 * output - -1 if error
377 * side effects - module is loaded if found.
378 */
379 int
380 load_one_module(const char *path)
381 {
382 dlink_node *ptr = NULL;
383 char modpath[HYB_PATH_MAX + 1];
384 struct stat statbuf;
385
386 DLINK_FOREACH(ptr, mod_paths.head)
387 {
388 const struct module_path *mpath = ptr->data;
389
390 snprintf(modpath, sizeof(modpath), "%s/%s", mpath->path, path);
391
392 if (!modules_valid_suffix(path))
393 continue;
394
395 if (strstr(modpath, "../") == NULL &&
396 strstr(modpath, "/..") == NULL)
397 if (!stat(modpath, &statbuf))
398 if (S_ISREG(statbuf.st_mode)) /* Regular files only please */
399 return load_a_module(modpath, 1);
400 }
401
402 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
403 "Cannot locate module %s", path);
404 ilog(LOG_TYPE_IRCD, "Cannot locate module %s", path);
405 return -1;
406 }

Properties

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