event-plugin.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  3. *
  4. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation;
  8. * version 2.1 of the License (not later!)
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this program; if not, see <http://www.gnu.org/licenses>
  17. *
  18. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19. */
  20. #include <string.h>
  21. #include <dlfcn.h>
  22. #include <stdlib.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <unistd.h>
  26. #include <dirent.h>
  27. #include "event-parse.h"
  28. #include "event-utils.h"
  29. #define LOCAL_PLUGIN_DIR ".traceevent/plugins"
  30. struct plugin_list {
  31. struct plugin_list *next;
  32. char *name;
  33. void *handle;
  34. };
  35. static void
  36. load_plugin(struct pevent *pevent, const char *path,
  37. const char *file, void *data)
  38. {
  39. struct plugin_list **plugin_list = data;
  40. pevent_plugin_load_func func;
  41. struct plugin_list *list;
  42. const char *alias;
  43. char *plugin;
  44. void *handle;
  45. plugin = malloc(strlen(path) + strlen(file) + 2);
  46. if (!plugin) {
  47. warning("could not allocate plugin memory\n");
  48. return;
  49. }
  50. strcpy(plugin, path);
  51. strcat(plugin, "/");
  52. strcat(plugin, file);
  53. handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
  54. if (!handle) {
  55. warning("could not load plugin '%s'\n%s\n",
  56. plugin, dlerror());
  57. goto out_free;
  58. }
  59. alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
  60. if (!alias)
  61. alias = file;
  62. func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
  63. if (!func) {
  64. warning("could not find func '%s' in plugin '%s'\n%s\n",
  65. PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
  66. goto out_free;
  67. }
  68. list = malloc(sizeof(*list));
  69. if (!list) {
  70. warning("could not allocate plugin memory\n");
  71. goto out_free;
  72. }
  73. list->next = *plugin_list;
  74. list->handle = handle;
  75. list->name = plugin;
  76. *plugin_list = list;
  77. pr_stat("registering plugin: %s", plugin);
  78. func(pevent);
  79. return;
  80. out_free:
  81. free(plugin);
  82. }
  83. static void
  84. load_plugins_dir(struct pevent *pevent, const char *suffix,
  85. const char *path,
  86. void (*load_plugin)(struct pevent *pevent,
  87. const char *path,
  88. const char *name,
  89. void *data),
  90. void *data)
  91. {
  92. struct dirent *dent;
  93. struct stat st;
  94. DIR *dir;
  95. int ret;
  96. ret = stat(path, &st);
  97. if (ret < 0)
  98. return;
  99. if (!S_ISDIR(st.st_mode))
  100. return;
  101. dir = opendir(path);
  102. if (!dir)
  103. return;
  104. while ((dent = readdir(dir))) {
  105. const char *name = dent->d_name;
  106. if (strcmp(name, ".") == 0 ||
  107. strcmp(name, "..") == 0)
  108. continue;
  109. /* Only load plugins that end in suffix */
  110. if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
  111. continue;
  112. load_plugin(pevent, path, name, data);
  113. }
  114. closedir(dir);
  115. }
  116. static void
  117. load_plugins(struct pevent *pevent, const char *suffix,
  118. void (*load_plugin)(struct pevent *pevent,
  119. const char *path,
  120. const char *name,
  121. void *data),
  122. void *data)
  123. {
  124. char *home;
  125. char *path;
  126. char *envdir;
  127. /*
  128. * If a system plugin directory was defined,
  129. * check that first.
  130. */
  131. #ifdef PLUGIN_DIR
  132. load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
  133. #endif
  134. /*
  135. * Next let the environment-set plugin directory
  136. * override the system defaults.
  137. */
  138. envdir = getenv("TRACEEVENT_PLUGIN_DIR");
  139. if (envdir)
  140. load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
  141. /*
  142. * Now let the home directory override the environment
  143. * or system defaults.
  144. */
  145. home = getenv("HOME");
  146. if (!home)
  147. return;
  148. path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
  149. if (!path) {
  150. warning("could not allocate plugin memory\n");
  151. return;
  152. }
  153. strcpy(path, home);
  154. strcat(path, "/");
  155. strcat(path, LOCAL_PLUGIN_DIR);
  156. load_plugins_dir(pevent, suffix, path, load_plugin, data);
  157. free(path);
  158. }
  159. struct plugin_list*
  160. traceevent_load_plugins(struct pevent *pevent)
  161. {
  162. struct plugin_list *list = NULL;
  163. load_plugins(pevent, ".so", load_plugin, &list);
  164. return list;
  165. }
  166. void
  167. traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent)
  168. {
  169. pevent_plugin_unload_func func;
  170. struct plugin_list *list;
  171. while (plugin_list) {
  172. list = plugin_list;
  173. plugin_list = list->next;
  174. func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
  175. if (func)
  176. func(pevent);
  177. dlclose(list->handle);
  178. free(list->name);
  179. free(list);
  180. }
  181. }