ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/modules.c
(Generate patch)

Comparing:
ircd-hybrid-7.3/src/modules.c (file contents), Revision 1029 by michael, Sun Nov 8 13:10:50 2009 UTC vs.
ircd-hybrid/trunk/src/modules.c (file contents), Revision 7032 by michael, Sun Jan 3 14:34:39 2016 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  modules.c: A module loader.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (c) 2000-2016 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
# Line 16 | Line 15
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
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
21 – *
22 – *  $Id$
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 "s_log.h"
32 > #include "log.h"
33   #include "ircd.h"
34   #include "client.h"
35   #include "send.h"
36 < #include "s_conf.h"
33 < #include "handlers.h"
36 > #include "conf.h"
37   #include "numeric.h"
38   #include "parse.h"
39   #include "ircd_defs.h"
# Line 38 | Line 41
41   #include "memory.h"
42  
43  
44 < dlink_list mod_list = { NULL, NULL, 0 };
44 > static dlink_list modules_list;
45 > static dlink_list modules_path;
46 > static dlink_list modules_conf;
47  
48 < static const char *core_module_table[] =
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",
# Line 55 | Line 62 | static const char *core_module_table[] =
62    "m_server.la",
63    "m_sjoin.la",
64    "m_squit.la",
65 +  "m_tmode.la",
66    NULL
67   };
68  
61 – static dlink_list mod_paths = { NULL, NULL, 0 };
62 – static dlink_list conf_modules = { NULL, NULL, 0 };
69  
70 < static void mo_modload(struct Client *, struct Client *, int, char *[]);
71 < static void mo_modlist(struct Client *, struct Client *, int, char *[]);
72 < static void mo_modreload(struct Client *, struct Client *, int, char *[]);
73 < static void mo_modunload(struct Client *, struct Client *, int, char *[]);
74 < static void mo_modrestart(struct Client *, struct Client *, int, char *[]);
69 <
70 < struct Message modload_msgtab = {
71 < "MODLOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
72 <  {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modload, m_ignore}
73 < };
70 > dlink_list *
71 > modules_get_list(void)
72 > {
73 >  return &modules_list;
74 > }
75  
76 < struct Message modunload_msgtab = {
77 < "MODUNLOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
78 <  {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modunload, m_ignore}
79 < };
76 > int
77 > modules_valid_suffix(const char *name)
78 > {
79 >  return ((name = strrchr(name, '.'))) && !strcmp(name, ".la");
80 > }
81  
82 < struct Message modreload_msgtab = {
83 <  "MODRELOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
84 <  {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modreload, m_ignore}
85 < };
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 < struct Message modlist_msgtab = {
95 < "MODLIST", 0, 0, 0, 0, MFLG_SLOW, 0,
87 <  {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modlist, m_ignore}
88 < };
94 >  if ((modp = findmodule_byname(name)) == NULL)
95 >    return -1;
96  
97 < struct Message modrestart_msgtab = {
98 < "MODRESTART", 0, 0, 0, 0, MFLG_SLOW, 0,
92 < {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modrestart, m_ignore}
93 < };
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)))
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
# Line 103 | Line 185 | struct Message modrestart_msgtab = {
185   void
186   modules_init(void)
187   {
188 <  dynlink_init();
189 <
190 <  mod_add_cmd(&modload_msgtab);
191 <  mod_add_cmd(&modunload_msgtab);
192 <  mod_add_cmd(&modreload_msgtab);
193 <  mod_add_cmd(&modlist_msgtab);
112 <  mod_add_cmd(&modrestart_msgtab);
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()
# Line 121 | Line 202 | modules_init(void)
202   static struct module_path *
203   mod_find_path(const char *path)
204   {
205 <  dlink_node *ptr;
125 <  struct module_path *mpath;
205 >  dlink_node *node = NULL;
206  
207 <  DLINK_FOREACH(ptr, mod_paths.head)
207 >  DLINK_FOREACH(node, modules_path.head)
208    {
209 <    mpath = ptr->data;
209 >    struct module_path *mpath = node->data;
210  
211      if (!strcmp(path, mpath->path))
212        return mpath;
# Line 149 | Line 229 | mod_add_path(const char *path)
229    if (mod_find_path(path))
230      return;
231  
232 <  pathst = MyMalloc(sizeof(struct module_path));
232 >  pathst = xcalloc(sizeof(struct module_path));
233  
234    strlcpy(pathst->path, path, sizeof(pathst->path));
235 <  dlinkAdd(pathst, &pathst->node, &mod_paths);
235 >  dlinkAdd(pathst, &pathst->node, &modules_path);
236   }
237  
238   /* add_conf_module
# Line 166 | Line 246 | add_conf_module(const char *name)
246   {
247    struct module_path *pathst;
248  
249 <  pathst = MyMalloc(sizeof(struct module_path));
249 >  pathst = xcalloc(sizeof(struct module_path));
250  
251    strlcpy(pathst->path, name, sizeof(pathst->path));
252 <  dlinkAdd(pathst, &pathst->node, &conf_modules);
252 >  dlinkAdd(pathst, &pathst->node, &modules_conf);
253   }
254  
255   /* mod_clear_paths()
# Line 181 | Line 261 | add_conf_module(const char *name)
261   void
262   mod_clear_paths(void)
263   {
264 <  struct module_path *pathst;
185 <  dlink_node *ptr;
186 <  dlink_node *next_ptr;
264 >  dlink_node *node = NULL, *node_next = NULL;
265  
266 <  DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
266 >  DLINK_FOREACH_SAFE(node, node_next, modules_path.head)
267    {
268 <    pathst = ptr->data;
269 <
192 <    dlinkDelete(&pathst->node, &mod_paths);
193 <    MyFree(pathst);
268 >    dlinkDelete(node, &modules_path);
269 >    xfree(node->data);
270    }
271  
272 <  DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
272 >  DLINK_FOREACH_SAFE(node, node_next, modules_conf.head)
273    {
274 <    pathst = ptr->data;
275 <
200 <    dlinkDelete(&pathst->node, &conf_modules);
201 <    MyFree(pathst);
274 >    dlinkDelete(node, &modules_conf);
275 >    xfree(node->data);
276    }
277   }
278  
# Line 208 | Line 282 | mod_clear_paths(void)
282   * output       - NULL if not found or pointer to module
283   * side effects - NONE
284   */
285 < dlink_node *
285 > struct module *
286   findmodule_byname(const char *name)
287   {
288 <  dlink_node *ptr;
215 <  struct module *modp;
288 >  dlink_node *node = NULL;
289  
290 <  DLINK_FOREACH(ptr, mod_list.head)
290 >  DLINK_FOREACH(node, modules_list.head)
291    {
292 <    modp = ptr->data;
292 >    struct module *modp = node->data;
293  
294 <    if (strcmp(modp->name, name) == 0)
295 <      return ptr;
294 >    if (!strcmp(modp->name, name))
295 >      return modp;
296    }
297  
298    return NULL;
# Line 236 | Line 309 | load_all_modules(int warn)
309   {
310    DIR *system_module_dir = NULL;
311    struct dirent *ldirent = NULL;
312 <  char module_fq_name[PATH_MAX + 1];
240 <
241 <  modules_init();
312 >  char module_fq_name[HYB_PATH_MAX + 1];
313  
314    if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
315    {
316 <    ilog(L_WARN, "Could not load modules from %s: %s",
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)) != NULL)
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, 0);
327 >       load_a_module(module_fq_name, warn);
328      }
329    }
330  
# Line 269 | Line 340 | load_all_modules(int warn)
340   void
341   load_conf_modules(void)
342   {
343 <  dlink_node *ptr = NULL;
273 <  struct module_path *mpath = NULL;
343 >  dlink_node *node = NULL;
344  
345 <  DLINK_FOREACH(ptr, conf_modules.head)
345 >  DLINK_FOREACH(node, modules_conf.head)
346    {
347 <    mpath = ptr->data;
347 >    struct module_path *mpath = node->data;
348  
349      if (findmodule_byname(mpath->path) == NULL)
350 <      load_one_module(mpath->path, 0);
350 >      load_one_module(mpath->path);
351    }
352   }
353  
# Line 290 | Line 360 | load_conf_modules(void)
360   void
361   load_core_modules(int warn)
362   {
363 <  char module_name[PATH_MAX + 1];
294 <  int i = 0;
363 >  char module_name[HYB_PATH_MAX + 1];
364  
365 <  for (; core_module_table[i]; ++i)
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) == -1)
370 >    if (load_a_module(module_name, warn) == -1)
371      {
372 <      ilog(L_CRIT, "Error loading core module %s: terminating ircd",
372 >      ilog(LOG_TYPE_IRCD, "Error loading core module %s: terminating ircd",
373             core_module_table[i]);
374        exit(EXIT_FAILURE);
375      }
# Line 311 | Line 380 | load_core_modules(int warn)
380   *
381   * input        - pointer to path
382   *              - flagged as core module or not
383 < * output       - -1 if error
383 > * output       - -1 if error
384   * side effects - module is loaded if found.
385   */
386   int
387 < load_one_module(const char *path, int coremodule)
387 > load_one_module(const char *name)
388   {
389 <  dlink_node *ptr = NULL;
390 <  char modpath[PATH_MAX + 1];
389 >  dlink_node *node = NULL;
390 >  char path[HYB_PATH_MAX + 1];
391    struct stat statbuf;
392  
393 <  DLINK_FOREACH(ptr, mod_paths.head)
393 >  DLINK_FOREACH(node, modules_path.head)
394    {
395 <    const struct module_path *mpath = ptr->data;
395 >    const struct module_path *mpath = node->data;
396  
397 <    snprintf(modpath, sizeof(modpath), "%s/%s", mpath->path, path);
397 >    snprintf(path, sizeof(path), "%s/%s", mpath->path, name);
398  
399 <    if (!modules_valid_suffix(path))
399 >    if (!modules_valid_suffix(name))
400        continue;
401  
402 <    if (strstr(modpath, "../") == NULL &&
403 <        strstr(modpath, "/..") == NULL)
404 <    {
405 <      if (!stat(modpath, &statbuf))
406 <      {
338 <        if (S_ISREG(statbuf.st_mode))
339 <        {
340 <          /* Regular files only please */
341 <          return load_a_module(modpath, 1, coremodule);
342 <        }
343 <      }
344 <    }
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_ALL, L_ALL,
410 <                       "Cannot locate module %s", path);
411 <  ilog(L_WARN, "Cannot locate module %s", path);
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   }
352 –
353 – /* load a module .. */
354 – static void
355 – mo_modload(struct Client *client_p, struct Client *source_p,
356 –           int parc, char *parv[])
357 – {
358 –  const char *m_bn = NULL;
359 –
360 –  if (!IsAdmin(source_p))
361 –  {
362 –    sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
363 –               me.name, source_p->name);
364 –    return;
365 –  }
366 –
367 –  m_bn = libio_basename(parv[1]);
368 –
369 –  if (findmodule_byname(m_bn) != NULL)
370 –  {
371 –    sendto_one(source_p, ":%s NOTICE %s :Module %s is already loaded",
372 –               me.name, source_p->name, m_bn);
373 –    return;
374 –  }
375 –
376 –  load_one_module(parv[1], 0);
377 – }
378 –
379 – /* unload a module .. */
380 – static void
381 – mo_modunload(struct Client *client_p, struct Client *source_p,
382 –             int parc, char *parv[])
383 – {
384 –  const char *m_bn = NULL;
385 –  dlink_node *ptr;
386 –  struct module *modp;
387 –
388 –  if (!IsAdmin(source_p))
389 –  {
390 –    sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
391 –               me.name, source_p->name);
392 –    return;
393 –  }
394 –
395 –  m_bn = libio_basename(parv[1]);
396 –
397 –  if ((ptr = findmodule_byname(m_bn)) == NULL)
398 –  {
399 –    sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
400 –               me.name, source_p->name, m_bn);
401 –    return;
402 –  }
403 –
404 –  modp = ptr->data;
405 –
406 –  if (modp->core == 1)
407 –  {
408 –    sendto_one(source_p,
409 –               ":%s NOTICE %s :Module %s is a core module and may not be unloaded",
410 –               me.name, source_p->name, m_bn);
411 –    return;
412 –  }
413 –
414 –  /* XXX might want to simply un dlink it here */
415 –
416 –  if (unload_one_module(m_bn, 1) == -1)
417 –  {
418 –    sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
419 –               me.name, source_p->name, m_bn);
420 –  }
421 – }
422 –
423 – /* unload and load in one! */
424 – static void
425 – mo_modreload(struct Client *client_p, struct Client *source_p,
426 –             int parc, char *parv[])
427 – {
428 –  const char *m_bn = NULL;
429 –  dlink_node *ptr;
430 –  struct module *modp;
431 –  int check_core;
432 –
433 –  if (!IsAdmin(source_p))
434 –  {
435 –    sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
436 –               me.name, source_p->name);
437 –    return;
438 –  }
439 –
440 –  m_bn = libio_basename(parv[1]);
441 –
442 –  if ((ptr = findmodule_byname(m_bn)) == NULL)
443 –  {
444 –    sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
445 –               me.name, source_p->name, m_bn);
446 –    return;
447 –  }
448 –
449 –  modp = ptr->data;
450 –  check_core = modp->core;
451 –
452 –  if (unload_one_module(m_bn, 1) == -1)
453 –  {
454 –    sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
455 –               me.name, source_p->name, m_bn);
456 –    return;
457 –  }
458 –
459 –  if ((load_one_module(parv[1], check_core) == -1) && check_core)
460 –  {
461 –    sendto_realops_flags(UMODE_ALL, L_ALL, "Error reloading core "
462 –                         "module: %s: terminating ircd", parv[1]);
463 –    ilog(L_CRIT, "Error loading core module %s: terminating ircd", parv[1]);
464 –    exit(0);
465 –  }
466 – }
467 –
468 – /* list modules .. */
469 – static void
470 – mo_modlist(struct Client *client_p, struct Client *source_p,
471 –           int parc, char *parv[])
472 – {
473 –  const dlink_node *ptr = NULL;
474 –
475 –  if (!IsAdmin(source_p))
476 –  {
477 –    sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
478 –               me.name, source_p->name);
479 –    return;
480 –  }
481 –
482 –  DLINK_FOREACH(ptr, mod_list.head)
483 –  {
484 –    const struct module *modp = ptr->data;
485 –
486 –    if (parc > 1 && !match(parv[1], modp->name))
487 –      continue;
488 –
489 –    sendto_one(source_p, form_str(RPL_MODLIST), me.name, parv[0],
490 –               modp->name, modp->handle,
491 –               modp->version, modp->core?"(core)":"");
492 –  }
493 –
494 –  sendto_one(source_p, form_str(RPL_ENDOFMODLIST),
495 –             me.name, source_p->name);
496 – }
497 –
498 – /* unload and reload all modules */
499 – static void
500 – mo_modrestart(struct Client *client_p, struct Client *source_p,
501 –              int parc, char *parv[])
502 – {
503 –  unsigned int modnum = 0;
504 –  dlink_node *ptr = NULL, *ptr_next = NULL;
505 –
506 –  if (!IsAdmin(source_p))
507 –  {
508 –    sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
509 –               me.name, source_p->name);
510 –    return;
511 –  }
512 –
513 –  sendto_one(source_p, ":%s NOTICE %s :Reloading all modules",
514 –             me.name, source_p->name);
515 –
516 –  modnum = dlink_list_length(&mod_list);
517 –
518 –  DLINK_FOREACH_SAFE(ptr, ptr_next, mod_list.head)
519 –  {
520 –    struct module *modp = ptr->data;
521 –    unload_one_module(modp->name, 0);
522 –  }
523 –
524 –  load_all_modules(0);
525 –  load_conf_modules();
526 –  load_core_modules(0);
527 –
528 –  sendto_realops_flags(UMODE_ALL, L_ALL,
529 –              "Module Restart: %u modules unloaded, %u modules loaded",
530 –                        modnum, dlink_list_length(&mod_list));
531 –  ilog(L_WARN, "Module Restart: %u modules unloaded, %u modules loaded",
532 –       modnum, dlink_list_length(&mod_list));
533 – }

Diff Legend

– Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)