ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/modules.c
Revision: 8431
Committed: Tue Mar 27 18:49:15 2018 UTC (7 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 9194 byte(s)
Log Message:
- Stylistic changes

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 2000-2018 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 xfree(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)) == NULL)
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;
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 = xcalloc(sizeof(*pathst));
233 pathst->path = xstrdup(path);
234 dlinkAdd(pathst, &pathst->node, &modules_path);
235 }
236
237 /* add_conf_module
238 *
239 * input - module name
240 * output - NONE
241 * side effects - adds module to conf_mod
242 */
243 void
244 add_conf_module(const char *name)
245 {
246 struct module_path *pathst;
247
248 pathst = xcalloc(sizeof(*pathst));
249 pathst->path = xstrdup(name);
250 dlinkAdd(pathst, &pathst->node, &modules_conf);
251 }
252
253 /* mod_clear_paths()
254 *
255 * input - NONE
256 * output - NONE
257 * side effects - clear the lists of paths and conf modules
258 */
259 void
260 modules_conf_clear(void)
261 {
262 while (modules_path.head)
263 {
264 struct module_path *path = modules_path.head->data;
265
266 dlinkDelete(&path->node, &modules_path);
267 xfree(path->path);
268 xfree(path);
269 }
270
271 while (modules_conf.head)
272 {
273 struct module_path *path = modules_conf.head->data;
274
275 dlinkDelete(&path->node, &modules_conf);
276 xfree(path->path);
277 xfree(path);
278 }
279 }
280
281 /* findmodule_byname
282 *
283 * input - name of module
284 * output - NULL if not found or pointer to module
285 * side effects - NONE
286 */
287 struct module *
288 findmodule_byname(const char *name)
289 {
290 dlink_node *node;
291
292 DLINK_FOREACH(node, modules_list.head)
293 {
294 struct module *modp = node->data;
295
296 if (!strcmp(modp->name, name))
297 return modp;
298 }
299
300 return NULL;
301 }
302
303 /* load_all_modules()
304 *
305 * input - int flag warn
306 * output - NONE
307 * side effects - load all modules found in autoload directory
308 */
309 void
310 load_all_modules(int warn)
311 {
312 DIR *system_module_dir = NULL;
313 struct dirent *ldirent = NULL;
314 char module_fq_name[HYB_PATH_MAX + 1];
315
316 if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
317 {
318 ilog(LOG_TYPE_IRCD, "Could not load modules from %s: %s",
319 AUTOMODPATH, strerror(errno));
320 return;
321 }
322
323 while ((ldirent = readdir(system_module_dir)))
324 {
325 if (modules_valid_suffix(ldirent->d_name))
326 {
327 snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
328 AUTOMODPATH, ldirent->d_name);
329 load_a_module(module_fq_name, warn);
330 }
331 }
332
333 closedir(system_module_dir);
334 }
335
336 /* load_conf_modules()
337 *
338 * input - NONE
339 * output - NONE
340 * side effects - load modules given in ircd.conf
341 */
342 void
343 load_conf_modules(void)
344 {
345 dlink_node *node;
346
347 DLINK_FOREACH(node, modules_conf.head)
348 {
349 struct module_path *mpath = node->data;
350
351 if (findmodule_byname(mpath->path) == NULL)
352 load_one_module(mpath->path);
353 }
354 }
355
356 /* load_core_modules()
357 *
358 * input - int flag warn
359 * output - NONE
360 * side effects - core modules are loaded, if any fail, kill ircd
361 */
362 void
363 load_core_modules(int warn)
364 {
365 char module_name[HYB_PATH_MAX + 1];
366
367 for (unsigned int i = 0; core_module_table[i]; ++i)
368 {
369 snprintf(module_name, sizeof(module_name), "%s%s",
370 MODPATH, core_module_table[i]);
371
372 if (load_a_module(module_name, warn) == -1)
373 {
374 ilog(LOG_TYPE_IRCD, "Error loading core module %s: terminating ircd",
375 core_module_table[i]);
376 exit(EXIT_FAILURE);
377 }
378 }
379 }
380
381 /* load_one_module()
382 *
383 * input - pointer to path
384 * - flagged as core module or not
385 * output - -1 if error
386 * side effects - module is loaded if found.
387 */
388 int
389 load_one_module(const char *name)
390 {
391 dlink_node *node;
392 char path[HYB_PATH_MAX + 1];
393 struct stat statbuf;
394
395 DLINK_FOREACH(node, modules_path.head)
396 {
397 const struct module_path *mpath = node->data;
398
399 snprintf(path, sizeof(path), "%s/%s", mpath->path, name);
400
401 if (!modules_valid_suffix(name))
402 continue;
403
404 if (strstr(path, "../") == NULL &&
405 strstr(path, "/..") == NULL)
406 if (!stat(path, &statbuf))
407 if (S_ISREG(statbuf.st_mode)) /* Regular files only please */
408 return load_a_module(path, 1);
409 }
410
411 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
412 "Cannot locate module %s", name);
413 ilog(LOG_TYPE_IRCD, "Cannot locate module %s", name);
414 return -1;
415 }

Properties

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