2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
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!)
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.
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>
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 #include <sys/types.h>
29 #include "event-parse.h"
30 #include "event-utils.h"
32 #define LOCAL_PLUGIN_DIR ".traceevent/plugins"
34 static struct registered_plugin_options {
35 struct registered_plugin_options *next;
36 struct pevent_plugin_option *options;
37 } *registered_options;
39 static struct trace_plugin_options {
40 struct trace_plugin_options *next;
44 } *trace_plugin_options;
47 struct plugin_list *next;
53 * traceevent_plugin_list_options - get list of plugin options
55 * Returns an array of char strings that list the currently registered
56 * plugin options in the format of <plugin>:<option>. This list can be
57 * used by toggling the option.
59 * Returns NULL if there's no options registered. On error it returns
60 * INVALID_PLUGIN_LIST_OPTION
62 * Must be freed with traceevent_plugin_free_options_list().
64 char **traceevent_plugin_list_options(void)
66 struct registered_plugin_options *reg;
67 struct pevent_plugin_option *op;
72 for (reg = registered_options; reg; reg = reg->next) {
73 for (op = reg->options; op->name; op++) {
74 char *alias = op->plugin_alias ? op->plugin_alias : op->file;
77 name = malloc(strlen(op->name) + strlen(alias) + 2);
81 sprintf(name, "%s:%s", alias, op->name);
82 list = realloc(list, count + 2);
99 return INVALID_PLUGIN_LIST_OPTION;
102 void traceevent_plugin_free_options_list(char **list)
109 if (list == INVALID_PLUGIN_LIST_OPTION)
112 for (i = 0; list[i]; i++)
119 update_option(const char *file, struct pevent_plugin_option *option)
121 struct trace_plugin_options *op;
124 if (option->plugin_alias) {
125 plugin = strdup(option->plugin_alias);
130 plugin = strdup(file);
133 p = strstr(plugin, ".");
138 /* first look for named options */
139 for (op = trace_plugin_options; op; op = op->next) {
142 if (strcmp(op->plugin, plugin) != 0)
144 if (strcmp(op->option, option->name) != 0)
147 option->value = op->value;
152 /* first look for unnamed options */
153 for (op = trace_plugin_options; op; op = op->next) {
156 if (strcmp(op->option, option->name) != 0)
159 option->value = op->value;
170 * traceevent_plugin_add_options - Add a set of options by a plugin
171 * @name: The name of the plugin adding the options
172 * @options: The set of options being loaded
174 * Sets the options with the values that have been added by user.
176 int traceevent_plugin_add_options(const char *name,
177 struct pevent_plugin_option *options)
179 struct registered_plugin_options *reg;
181 reg = malloc(sizeof(*reg));
184 reg->next = registered_options;
185 reg->options = options;
186 registered_options = reg;
188 while (options->name) {
189 update_option(name, options);
196 * traceevent_plugin_remove_options - remove plugin options that were registered
197 * @options: Options to removed that were registered with traceevent_plugin_add_options
199 void traceevent_plugin_remove_options(struct pevent_plugin_option *options)
201 struct registered_plugin_options **last;
202 struct registered_plugin_options *reg;
204 for (last = ®istered_options; *last; last = &(*last)->next) {
205 if ((*last)->options == options) {
215 * traceevent_print_plugins - print out the list of plugins loaded
216 * @s: the trace_seq descripter to write to
217 * @prefix: The prefix string to add before listing the option name
218 * @suffix: The suffix string ot append after the option name
219 * @list: The list of plugins (usually returned by traceevent_load_plugins()
221 * Writes to the trace_seq @s the list of plugins (files) that is
222 * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating:
223 * @prefix = " ", @suffix = "\n".
225 void traceevent_print_plugins(struct trace_seq *s,
226 const char *prefix, const char *suffix,
227 const struct plugin_list *list)
230 trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix);
236 load_plugin(struct pevent *pevent, const char *path,
237 const char *file, void *data)
239 struct plugin_list **plugin_list = data;
240 pevent_plugin_load_func func;
241 struct plugin_list *list;
246 plugin = malloc(strlen(path) + strlen(file) + 2);
248 warning("could not allocate plugin memory\n");
252 strcpy(plugin, path);
254 strcat(plugin, file);
256 handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
258 warning("could not load plugin '%s'\n%s\n",
263 alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
267 func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
269 warning("could not find func '%s' in plugin '%s'\n%s\n",
270 PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
274 list = malloc(sizeof(*list));
276 warning("could not allocate plugin memory\n");
280 list->next = *plugin_list;
281 list->handle = handle;
285 pr_stat("registering plugin: %s", plugin);
294 load_plugins_dir(struct pevent *pevent, const char *suffix,
296 void (*load_plugin)(struct pevent *pevent,
307 ret = stat(path, &st);
311 if (!S_ISDIR(st.st_mode))
318 while ((dent = readdir(dir))) {
319 const char *name = dent->d_name;
321 if (strcmp(name, ".") == 0 ||
322 strcmp(name, "..") == 0)
325 /* Only load plugins that end in suffix */
326 if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
329 load_plugin(pevent, path, name, data);
336 load_plugins(struct pevent *pevent, const char *suffix,
337 void (*load_plugin)(struct pevent *pevent,
347 if (pevent->flags & PEVENT_DISABLE_PLUGINS)
351 * If a system plugin directory was defined,
355 if (!(pevent->flags & PEVENT_DISABLE_SYS_PLUGINS))
356 load_plugins_dir(pevent, suffix, PLUGIN_DIR,
361 * Next let the environment-set plugin directory
362 * override the system defaults.
364 envdir = getenv("TRACEEVENT_PLUGIN_DIR");
366 load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
369 * Now let the home directory override the environment
370 * or system defaults.
372 home = getenv("HOME");
376 path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
378 warning("could not allocate plugin memory\n");
384 strcat(path, LOCAL_PLUGIN_DIR);
386 load_plugins_dir(pevent, suffix, path, load_plugin, data);
392 traceevent_load_plugins(struct pevent *pevent)
394 struct plugin_list *list = NULL;
396 load_plugins(pevent, ".so", load_plugin, &list);
401 traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent)
403 pevent_plugin_unload_func func;
404 struct plugin_list *list;
406 while (plugin_list) {
408 plugin_list = list->next;
409 func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
412 dlclose(list->handle);