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
);