| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; | 
					
						
							|  |  |  |  * version 2.1 of the License (not later!) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with this program; if not,  see <http://www.gnu.org/licenses>
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 09:57:54 -04:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <dlfcn.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <dirent.h>
 | 
					
						
							|  |  |  | #include "event-parse.h"
 | 
					
						
							|  |  |  | #include "event-utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LOCAL_PLUGIN_DIR ".traceevent/plugins"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | static struct registered_plugin_options { | 
					
						
							|  |  |  | 	struct registered_plugin_options	*next; | 
					
						
							|  |  |  | 	struct pevent_plugin_option		*options; | 
					
						
							|  |  |  | } *registered_options; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct trace_plugin_options { | 
					
						
							|  |  |  | 	struct trace_plugin_options	*next; | 
					
						
							|  |  |  | 	char				*plugin; | 
					
						
							|  |  |  | 	char				*option; | 
					
						
							|  |  |  | 	char				*value; | 
					
						
							|  |  |  | } *trace_plugin_options; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | struct plugin_list { | 
					
						
							|  |  |  | 	struct plugin_list	*next; | 
					
						
							|  |  |  | 	char			*name; | 
					
						
							|  |  |  | 	void			*handle; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 09:57:54 -04:00
										 |  |  | static void lower_case(char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!str) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	for (; *str; str++) | 
					
						
							|  |  |  | 		*str = tolower(*str); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int update_option_value(struct pevent_plugin_option *op, const char *val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *op_val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!val) { | 
					
						
							|  |  |  | 		/* toggle, only if option is boolean */ | 
					
						
							|  |  |  | 		if (op->value) | 
					
						
							|  |  |  | 			/* Warn? */ | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		op->set ^= 1; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * If the option has a value then it takes a string | 
					
						
							|  |  |  | 	 * otherwise the option is a boolean. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (op->value) { | 
					
						
							|  |  |  | 		op->value = val; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Option is boolean, must be either "1", "0", "true" or "false" */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	op_val = strdup(val); | 
					
						
							|  |  |  | 	if (!op_val) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	lower_case(op_val); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0) | 
					
						
							|  |  |  | 		op->set = 1; | 
					
						
							|  |  |  | 	else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0) | 
					
						
							|  |  |  | 		op->set = 0; | 
					
						
							|  |  |  | 	free(op_val); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * traceevent_plugin_list_options - get list of plugin options | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns an array of char strings that list the currently registered | 
					
						
							|  |  |  |  * plugin options in the format of <plugin>:<option>. This list can be | 
					
						
							|  |  |  |  * used by toggling the option. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns NULL if there's no options registered. On error it returns | 
					
						
							|  |  |  |  * INVALID_PLUGIN_LIST_OPTION | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Must be freed with traceevent_plugin_free_options_list(). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | char **traceevent_plugin_list_options(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct registered_plugin_options *reg; | 
					
						
							|  |  |  | 	struct pevent_plugin_option *op; | 
					
						
							|  |  |  | 	char **list = NULL; | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (reg = registered_options; reg; reg = reg->next) { | 
					
						
							|  |  |  | 		for (op = reg->options; op->name; op++) { | 
					
						
							|  |  |  | 			char *alias = op->plugin_alias ? op->plugin_alias : op->file; | 
					
						
							|  |  |  | 			char **temp = list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			name = malloc(strlen(op->name) + strlen(alias) + 2); | 
					
						
							|  |  |  | 			if (!name) | 
					
						
							|  |  |  | 				goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sprintf(name, "%s:%s", alias, op->name); | 
					
						
							|  |  |  | 			list = realloc(list, count + 2); | 
					
						
							|  |  |  | 			if (!list) { | 
					
						
							|  |  |  | 				list = temp; | 
					
						
							|  |  |  | 				free(name); | 
					
						
							|  |  |  | 				goto err; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			list[count++] = name; | 
					
						
							|  |  |  | 			list[count] = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  | 	while (--count >= 0) | 
					
						
							|  |  |  | 		free(list[count]); | 
					
						
							|  |  |  | 	free(list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return INVALID_PLUGIN_LIST_OPTION; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void traceevent_plugin_free_options_list(char **list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!list) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (list == INVALID_PLUGIN_LIST_OPTION) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; list[i]; i++) | 
					
						
							|  |  |  | 		free(list[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	free(list); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | update_option(const char *file, struct pevent_plugin_option *option) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct trace_plugin_options *op; | 
					
						
							|  |  |  | 	char *plugin; | 
					
						
							| 
									
										
										
										
											2015-03-24 09:57:54 -04:00
										 |  |  | 	int ret = 0; | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (option->plugin_alias) { | 
					
						
							|  |  |  | 		plugin = strdup(option->plugin_alias); | 
					
						
							|  |  |  | 		if (!plugin) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		char *p; | 
					
						
							|  |  |  | 		plugin = strdup(file); | 
					
						
							|  |  |  | 		if (!plugin) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		p = strstr(plugin, "."); | 
					
						
							|  |  |  | 		if (p) | 
					
						
							|  |  |  | 			*p = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first look for named options */ | 
					
						
							|  |  |  | 	for (op = trace_plugin_options; op; op = op->next) { | 
					
						
							|  |  |  | 		if (!op->plugin) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (strcmp(op->plugin, plugin) != 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (strcmp(op->option, option->name) != 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 09:57:54 -04:00
										 |  |  | 		ret = update_option_value(option, op->value); | 
					
						
							|  |  |  | 		if (ret) | 
					
						
							|  |  |  | 			goto out; | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first look for unnamed options */ | 
					
						
							|  |  |  | 	for (op = trace_plugin_options; op; op = op->next) { | 
					
						
							|  |  |  | 		if (op->plugin) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (strcmp(op->option, option->name) != 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 09:57:54 -04:00
										 |  |  | 		ret = update_option_value(option, op->value); | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out: | 
					
						
							|  |  |  | 	free(plugin); | 
					
						
							| 
									
										
										
										
											2015-03-24 09:57:54 -04:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2014-06-03 18:41:54 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * traceevent_plugin_add_options - Add a set of options by a plugin | 
					
						
							|  |  |  |  * @name: The name of the plugin adding the options | 
					
						
							|  |  |  |  * @options: The set of options being loaded | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Sets the options with the values that have been added by user. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int traceevent_plugin_add_options(const char *name, | 
					
						
							|  |  |  | 				  struct pevent_plugin_option *options) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct registered_plugin_options *reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	reg = malloc(sizeof(*reg)); | 
					
						
							|  |  |  | 	if (!reg) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	reg->next = registered_options; | 
					
						
							|  |  |  | 	reg->options = options; | 
					
						
							|  |  |  | 	registered_options = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (options->name) { | 
					
						
							|  |  |  | 		update_option(name, options); | 
					
						
							|  |  |  | 		options++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * traceevent_plugin_remove_options - remove plugin options that were registered | 
					
						
							|  |  |  |  * @options: Options to removed that were registered with traceevent_plugin_add_options | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void traceevent_plugin_remove_options(struct pevent_plugin_option *options) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct registered_plugin_options **last; | 
					
						
							|  |  |  | 	struct registered_plugin_options *reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (last = ®istered_options; *last; last = &(*last)->next) { | 
					
						
							|  |  |  | 		if ((*last)->options == options) { | 
					
						
							|  |  |  | 			reg = *last; | 
					
						
							|  |  |  | 			*last = reg->next; | 
					
						
							|  |  |  | 			free(reg); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * traceevent_print_plugins - print out the list of plugins loaded | 
					
						
							|  |  |  |  * @s: the trace_seq descripter to write to | 
					
						
							|  |  |  |  * @prefix: The prefix string to add before listing the option name | 
					
						
							|  |  |  |  * @suffix: The suffix string ot append after the option name | 
					
						
							|  |  |  |  * @list: The list of plugins (usually returned by traceevent_load_plugins() | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Writes to the trace_seq @s the list of plugins (files) that is | 
					
						
							|  |  |  |  * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating: | 
					
						
							|  |  |  |  * @prefix = "  ", @suffix = "\n". | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void traceevent_print_plugins(struct trace_seq *s, | 
					
						
							|  |  |  | 			      const char *prefix, const char *suffix, | 
					
						
							|  |  |  | 			      const struct plugin_list *list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	while (list) { | 
					
						
							|  |  |  | 		trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix); | 
					
						
							|  |  |  | 		list = list->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | load_plugin(struct pevent *pevent, const char *path, | 
					
						
							|  |  |  | 	    const char *file, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct plugin_list **plugin_list = data; | 
					
						
							|  |  |  | 	pevent_plugin_load_func func; | 
					
						
							|  |  |  | 	struct plugin_list *list; | 
					
						
							|  |  |  | 	const char *alias; | 
					
						
							|  |  |  | 	char *plugin; | 
					
						
							|  |  |  | 	void *handle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:36 +01:00
										 |  |  | 	plugin = malloc(strlen(path) + strlen(file) + 2); | 
					
						
							|  |  |  | 	if (!plugin) { | 
					
						
							|  |  |  | 		warning("could not allocate plugin memory\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	strcpy(plugin, path); | 
					
						
							|  |  |  | 	strcat(plugin, "/"); | 
					
						
							|  |  |  | 	strcat(plugin, file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL); | 
					
						
							|  |  |  | 	if (!handle) { | 
					
						
							|  |  |  | 		warning("could not load plugin '%s'\n%s\n", | 
					
						
							|  |  |  | 			plugin, dlerror()); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME); | 
					
						
							|  |  |  | 	if (!alias) | 
					
						
							|  |  |  | 		alias = file; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); | 
					
						
							|  |  |  | 	if (!func) { | 
					
						
							|  |  |  | 		warning("could not find func '%s' in plugin '%s'\n%s\n", | 
					
						
							|  |  |  | 			PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror()); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:36 +01:00
										 |  |  | 	list = malloc(sizeof(*list)); | 
					
						
							|  |  |  | 	if (!list) { | 
					
						
							|  |  |  | 		warning("could not allocate plugin memory\n"); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | 	list->next = *plugin_list; | 
					
						
							|  |  |  | 	list->handle = handle; | 
					
						
							|  |  |  | 	list->name = plugin; | 
					
						
							|  |  |  | 	*plugin_list = list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pr_stat("registering plugin: %s", plugin); | 
					
						
							|  |  |  | 	func(pevent); | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  out_free: | 
					
						
							|  |  |  | 	free(plugin); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | load_plugins_dir(struct pevent *pevent, const char *suffix, | 
					
						
							|  |  |  | 		 const char *path, | 
					
						
							|  |  |  | 		 void (*load_plugin)(struct pevent *pevent, | 
					
						
							|  |  |  | 				     const char *path, | 
					
						
							|  |  |  | 				     const char *name, | 
					
						
							|  |  |  | 				     void *data), | 
					
						
							|  |  |  | 		 void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct dirent *dent; | 
					
						
							|  |  |  | 	struct stat st; | 
					
						
							|  |  |  | 	DIR *dir; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = stat(path, &st); | 
					
						
							|  |  |  | 	if (ret < 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!S_ISDIR(st.st_mode)) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dir = opendir(path); | 
					
						
							|  |  |  | 	if (!dir) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((dent = readdir(dir))) { | 
					
						
							|  |  |  | 		const char *name = dent->d_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (strcmp(name, ".") == 0 || | 
					
						
							|  |  |  | 		    strcmp(name, "..") == 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Only load plugins that end in suffix */ | 
					
						
							|  |  |  | 		if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		load_plugin(pevent, path, name, data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	closedir(dir); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | load_plugins(struct pevent *pevent, const char *suffix, | 
					
						
							|  |  |  | 	     void (*load_plugin)(struct pevent *pevent, | 
					
						
							|  |  |  | 				 const char *path, | 
					
						
							|  |  |  | 				 const char *name, | 
					
						
							|  |  |  | 				 void *data), | 
					
						
							|  |  |  | 	     void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *home; | 
					
						
							|  |  |  | 	char *path; | 
					
						
							|  |  |  | 	char *envdir; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-02 23:20:13 -04:00
										 |  |  | 	if (pevent->flags & PEVENT_DISABLE_PLUGINS) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * If a system plugin directory was defined, | 
					
						
							|  |  |  | 	 * check that first. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | #ifdef PLUGIN_DIR
 | 
					
						
							| 
									
										
										
										
											2014-06-02 23:20:13 -04:00
										 |  |  | 	if (!(pevent->flags & PEVENT_DISABLE_SYS_PLUGINS)) | 
					
						
							|  |  |  | 		load_plugins_dir(pevent, suffix, PLUGIN_DIR, | 
					
						
							|  |  |  | 				 load_plugin, data); | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Next let the environment-set plugin directory | 
					
						
							|  |  |  | 	 * override the system defaults. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	envdir = getenv("TRACEEVENT_PLUGIN_DIR"); | 
					
						
							|  |  |  | 	if (envdir) | 
					
						
							|  |  |  | 		load_plugins_dir(pevent, suffix, envdir, load_plugin, data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Now let the home directory override the environment | 
					
						
							|  |  |  | 	 * or system defaults. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	home = getenv("HOME"); | 
					
						
							|  |  |  | 	if (!home) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:36 +01:00
										 |  |  | 	path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2); | 
					
						
							|  |  |  | 	if (!path) { | 
					
						
							|  |  |  | 		warning("could not allocate plugin memory\n"); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	strcpy(path, home); | 
					
						
							|  |  |  | 	strcat(path, "/"); | 
					
						
							|  |  |  | 	strcat(path, LOCAL_PLUGIN_DIR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	load_plugins_dir(pevent, suffix, path, load_plugin, data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	free(path); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct plugin_list* | 
					
						
							|  |  |  | traceevent_load_plugins(struct pevent *pevent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct plugin_list *list = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	load_plugins(pevent, ".so", load_plugin, &list); | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2014-01-15 10:45:28 +09:00
										 |  |  | traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent) | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	pevent_plugin_unload_func func; | 
					
						
							|  |  |  | 	struct plugin_list *list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (plugin_list) { | 
					
						
							|  |  |  | 		list = plugin_list; | 
					
						
							|  |  |  | 		plugin_list = list->next; | 
					
						
							|  |  |  | 		func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME); | 
					
						
							|  |  |  | 		if (func) | 
					
						
							| 
									
										
										
										
											2014-01-15 10:45:28 +09:00
										 |  |  | 			func(pevent); | 
					
						
							| 
									
										
										
										
											2013-12-03 14:09:16 +01:00
										 |  |  | 		dlclose(list->handle); | 
					
						
							|  |  |  | 		free(list->name); | 
					
						
							|  |  |  | 		free(list); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |