ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.1.x/src/modules.c
Revision: 1996
Committed: Sat May 11 17:34:41 2013 UTC (10 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 9078 byte(s)
Log Message:
- Mostly style cleanups & whitespace changes

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 "ltdl.h"
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "modules.h"
30 #include "log.h"
31 #include "ircd.h"
32 #include "client.h"
33 #include "send.h"
34 #include "conf.h"
35 #include "numeric.h"
36 #include "parse.h"
37 #include "ircd_defs.h"
38 #include "irc_string.h"
39 #include "memory.h"
40
41
42 dlink_list modules_list = { NULL, NULL, 0 };
43
44 static dlink_list mod_paths = { NULL, NULL, 0 };
45 static dlink_list conf_modules = { NULL, NULL, 0 };
46
47 static const char *unknown_ver = "<unknown>";
48 static const char *core_module_table[] =
49 {
50 "m_die.la",
51 "m_error.la",
52 "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 NULL
64 };
65
66 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 assert(dlink_list_length(&modules_list) > 0);
91 dlinkDelete(&modp->node, &modules_list);
92 MyFree(modp->name);
93
94 lt_dlclose(modp->handle);
95
96 if (warn == 1)
97 {
98 ilog(LOG_TYPE_IRCD, "Module %s unloaded", name);
99 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
100 "Module %s unloaded", name);
101 }
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 load_a_module(const char *path, int warn)
114 {
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 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
126 "Error loading module %s: %s",
127 mod_basename, err);
128 ilog(LOG_TYPE_IRCD, "Error loading module %s: %s", mod_basename, err);
129 return -1;
130 }
131
132 if ((modp = lt_dlsym(tmpptr, "module_entry")) == NULL)
133 {
134 const char *err = ((err = lt_dlerror())) ? err : "<unknown>";
135
136 sendto_realops_flags(UMODE_ALL, 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 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 modp->name = xstrdup(mod_basename);
150 dlinkAdd(modp, &modp->node, &modules_list);
151
152 if (modp->modinit)
153 modp->modinit();
154
155 if (warn == 1)
156 {
157 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
158 "Module %s [version: %s handle: %p] loaded.",
159 modp->name, modp->version, tmpptr);
160 ilog(LOG_TYPE_IRCD, "Module %s [version: %s handle: %p] loaded.",
161 modp->name, modp->version, tmpptr);
162 }
163
164 return 0;
165 }
166
167 /*
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 if (lt_dlinit())
178 {
179 ilog(LOG_TYPE_IRCD, "Couldn't initialize the libltdl run time dynamic"
180 " link library. Exiting.");
181 exit(0);
182 }
183 }
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 struct module_path *mpath = ptr->data;
199
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 dlink_node *ptr = NULL, *next_ptr = NULL;
254
255 DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
256 {
257 dlinkDelete(ptr, &mod_paths);
258 MyFree(ptr->data);
259 }
260
261 DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
262 {
263 dlinkDelete(ptr, &conf_modules);
264 MyFree(ptr->data);
265 }
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 struct module *
275 findmodule_byname(const char *name)
276 {
277 dlink_node *ptr = NULL;
278
279 DLINK_FOREACH(ptr, modules_list.head)
280 {
281 struct module *modp = ptr->data;
282
283 if (strcmp(modp->name, name) == 0)
284 return modp;
285 }
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 char module_fq_name[HYB_PATH_MAX + 1];
302
303 if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
304 {
305 ilog(LOG_TYPE_IRCD, "Could not load modules from %s: %s",
306 AUTOMODPATH, strerror(errno));
307 return;
308 }
309
310 while ((ldirent = readdir(system_module_dir)) != NULL)
311 {
312 if (modules_valid_suffix(ldirent->d_name))
313 {
314 snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
315 AUTOMODPATH, ldirent->d_name);
316 load_a_module(module_fq_name, warn);
317 }
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 struct module_path *mpath = ptr->data;
337
338 if (findmodule_byname(mpath->path) == NULL)
339 load_one_module(mpath->path);
340 }
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 char module_name[HYB_PATH_MAX + 1];
353 int i = 0;
354
355 for (; core_module_table[i]; ++i)
356 {
357 snprintf(module_name, sizeof(module_name), "%s%s",
358 MODPATH, core_module_table[i]);
359
360 if (load_a_module(module_name, warn) == -1)
361 {
362 ilog(LOG_TYPE_IRCD, "Error loading core module %s: terminating ircd",
363 core_module_table[i]);
364 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 * output - -1 if error
374 * side effects - module is loaded if found.
375 */
376 int
377 load_one_module(const char *path)
378 {
379 dlink_node *ptr = NULL;
380 char modpath[HYB_PATH_MAX + 1];
381 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 if (!modules_valid_suffix(path))
390 continue;
391
392 if (strstr(modpath, "../") == NULL &&
393 strstr(modpath, "/..") == NULL)
394 if (!stat(modpath, &statbuf))
395 if (S_ISREG(statbuf.st_mode)) /* Regular files only please */
396 return load_a_module(modpath, 1);
397 }
398
399 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
400 "Cannot locate module %s", path);
401 ilog(LOG_TYPE_IRCD, "Cannot locate module %s", path);
402 return -1;
403 }

Properties

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