xref: /aosp_15_r20/external/libtraceevent/src/event-plugin.c (revision 436bf2bcd5202612ffffe471bbcc1f277cc8d28e)
1*436bf2bcSAndroid Build Coastguard Worker // SPDX-License-Identifier: LGPL-2.1
2*436bf2bcSAndroid Build Coastguard Worker /*
3*436bf2bcSAndroid Build Coastguard Worker  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
4*436bf2bcSAndroid Build Coastguard Worker  *
5*436bf2bcSAndroid Build Coastguard Worker  */
6*436bf2bcSAndroid Build Coastguard Worker 
7*436bf2bcSAndroid Build Coastguard Worker #include <ctype.h>
8*436bf2bcSAndroid Build Coastguard Worker #include <stdio.h>
9*436bf2bcSAndroid Build Coastguard Worker #include <string.h>
10*436bf2bcSAndroid Build Coastguard Worker #include <dlfcn.h>
11*436bf2bcSAndroid Build Coastguard Worker #include <stdlib.h>
12*436bf2bcSAndroid Build Coastguard Worker #include <sys/types.h>
13*436bf2bcSAndroid Build Coastguard Worker #include <sys/stat.h>
14*436bf2bcSAndroid Build Coastguard Worker #include <unistd.h>
15*436bf2bcSAndroid Build Coastguard Worker #include <dirent.h>
16*436bf2bcSAndroid Build Coastguard Worker #include <errno.h>
17*436bf2bcSAndroid Build Coastguard Worker #include "event-parse.h"
18*436bf2bcSAndroid Build Coastguard Worker #include "event-parse-local.h"
19*436bf2bcSAndroid Build Coastguard Worker #include "event-utils.h"
20*436bf2bcSAndroid Build Coastguard Worker #include "trace-seq.h"
21*436bf2bcSAndroid Build Coastguard Worker 
22*436bf2bcSAndroid Build Coastguard Worker #define LOCAL_PLUGIN_DIR ".local/lib/traceevent/plugins/"
23*436bf2bcSAndroid Build Coastguard Worker 
24*436bf2bcSAndroid Build Coastguard Worker static struct registered_plugin_options {
25*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options	*next;
26*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_option		*options;
27*436bf2bcSAndroid Build Coastguard Worker } *registered_options;
28*436bf2bcSAndroid Build Coastguard Worker 
29*436bf2bcSAndroid Build Coastguard Worker static struct trace_plugin_options {
30*436bf2bcSAndroid Build Coastguard Worker 	struct trace_plugin_options	*next;
31*436bf2bcSAndroid Build Coastguard Worker 	char				*plugin;
32*436bf2bcSAndroid Build Coastguard Worker 	char				*option;
33*436bf2bcSAndroid Build Coastguard Worker 	char				*value;
34*436bf2bcSAndroid Build Coastguard Worker } *trace_plugin_options;
35*436bf2bcSAndroid Build Coastguard Worker 
36*436bf2bcSAndroid Build Coastguard Worker struct tep_plugin_list {
37*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_list	*next;
38*436bf2bcSAndroid Build Coastguard Worker 	char			*name;
39*436bf2bcSAndroid Build Coastguard Worker 	void			*handle;
40*436bf2bcSAndroid Build Coastguard Worker };
41*436bf2bcSAndroid Build Coastguard Worker 
42*436bf2bcSAndroid Build Coastguard Worker struct tep_plugins_dir {
43*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugins_dir		*next;
44*436bf2bcSAndroid Build Coastguard Worker 	char				*path;
45*436bf2bcSAndroid Build Coastguard Worker 	enum tep_plugin_load_priority	prio;
46*436bf2bcSAndroid Build Coastguard Worker };
47*436bf2bcSAndroid Build Coastguard Worker 
lower_case(char * str)48*436bf2bcSAndroid Build Coastguard Worker static void lower_case(char *str)
49*436bf2bcSAndroid Build Coastguard Worker {
50*436bf2bcSAndroid Build Coastguard Worker 	if (!str)
51*436bf2bcSAndroid Build Coastguard Worker 		return;
52*436bf2bcSAndroid Build Coastguard Worker 	for (; *str; str++)
53*436bf2bcSAndroid Build Coastguard Worker 		*str = tolower(*str);
54*436bf2bcSAndroid Build Coastguard Worker }
55*436bf2bcSAndroid Build Coastguard Worker 
update_option_value(struct tep_plugin_option * op,const char * val)56*436bf2bcSAndroid Build Coastguard Worker static int update_option_value(struct tep_plugin_option *op, const char *val)
57*436bf2bcSAndroid Build Coastguard Worker {
58*436bf2bcSAndroid Build Coastguard Worker 	char *op_val;
59*436bf2bcSAndroid Build Coastguard Worker 
60*436bf2bcSAndroid Build Coastguard Worker 	if (!val) {
61*436bf2bcSAndroid Build Coastguard Worker 		/* toggle, only if option is boolean */
62*436bf2bcSAndroid Build Coastguard Worker 		if (op->value)
63*436bf2bcSAndroid Build Coastguard Worker 			/* Warn? */
64*436bf2bcSAndroid Build Coastguard Worker 			return 0;
65*436bf2bcSAndroid Build Coastguard Worker 		op->set ^= 1;
66*436bf2bcSAndroid Build Coastguard Worker 		return 0;
67*436bf2bcSAndroid Build Coastguard Worker 	}
68*436bf2bcSAndroid Build Coastguard Worker 
69*436bf2bcSAndroid Build Coastguard Worker 	/*
70*436bf2bcSAndroid Build Coastguard Worker 	 * If the option has a value then it takes a string
71*436bf2bcSAndroid Build Coastguard Worker 	 * otherwise the option is a boolean.
72*436bf2bcSAndroid Build Coastguard Worker 	 */
73*436bf2bcSAndroid Build Coastguard Worker 	if (op->value) {
74*436bf2bcSAndroid Build Coastguard Worker 		op->value = val;
75*436bf2bcSAndroid Build Coastguard Worker 		return 0;
76*436bf2bcSAndroid Build Coastguard Worker 	}
77*436bf2bcSAndroid Build Coastguard Worker 
78*436bf2bcSAndroid Build Coastguard Worker 	/* Option is boolean, must be either "1", "0", "true" or "false" */
79*436bf2bcSAndroid Build Coastguard Worker 
80*436bf2bcSAndroid Build Coastguard Worker 	op_val = strdup(val);
81*436bf2bcSAndroid Build Coastguard Worker 	if (!op_val)
82*436bf2bcSAndroid Build Coastguard Worker 		return -1;
83*436bf2bcSAndroid Build Coastguard Worker 	lower_case(op_val);
84*436bf2bcSAndroid Build Coastguard Worker 
85*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0)
86*436bf2bcSAndroid Build Coastguard Worker 		op->set = 1;
87*436bf2bcSAndroid Build Coastguard Worker 	else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0)
88*436bf2bcSAndroid Build Coastguard Worker 		op->set = 0;
89*436bf2bcSAndroid Build Coastguard Worker 	free(op_val);
90*436bf2bcSAndroid Build Coastguard Worker 
91*436bf2bcSAndroid Build Coastguard Worker 	return 0;
92*436bf2bcSAndroid Build Coastguard Worker }
93*436bf2bcSAndroid Build Coastguard Worker 
94*436bf2bcSAndroid Build Coastguard Worker /**
95*436bf2bcSAndroid Build Coastguard Worker  * tep_plugin_list_options - get list of plugin options
96*436bf2bcSAndroid Build Coastguard Worker  *
97*436bf2bcSAndroid Build Coastguard Worker  * Returns an array of char strings that list the currently registered
98*436bf2bcSAndroid Build Coastguard Worker  * plugin options in the format of <plugin>:<option>. This list can be
99*436bf2bcSAndroid Build Coastguard Worker  * used by toggling the option.
100*436bf2bcSAndroid Build Coastguard Worker  *
101*436bf2bcSAndroid Build Coastguard Worker  * Returns NULL if there's no options registered. On error it returns
102*436bf2bcSAndroid Build Coastguard Worker  * INVALID_PLUGIN_LIST_OPTION
103*436bf2bcSAndroid Build Coastguard Worker  *
104*436bf2bcSAndroid Build Coastguard Worker  * Must be freed with tep_plugin_free_options_list().
105*436bf2bcSAndroid Build Coastguard Worker  */
tep_plugin_list_options(void)106*436bf2bcSAndroid Build Coastguard Worker char **tep_plugin_list_options(void)
107*436bf2bcSAndroid Build Coastguard Worker {
108*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options *reg;
109*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_option *op;
110*436bf2bcSAndroid Build Coastguard Worker 	char **list = NULL;
111*436bf2bcSAndroid Build Coastguard Worker 	char *name;
112*436bf2bcSAndroid Build Coastguard Worker 	int count = 0;
113*436bf2bcSAndroid Build Coastguard Worker 
114*436bf2bcSAndroid Build Coastguard Worker 	for (reg = registered_options; reg; reg = reg->next) {
115*436bf2bcSAndroid Build Coastguard Worker 		for (op = reg->options; op->name; op++) {
116*436bf2bcSAndroid Build Coastguard Worker 			char *alias = op->plugin_alias ? op->plugin_alias : op->file;
117*436bf2bcSAndroid Build Coastguard Worker 			char **temp = list;
118*436bf2bcSAndroid Build Coastguard Worker 			int ret;
119*436bf2bcSAndroid Build Coastguard Worker 
120*436bf2bcSAndroid Build Coastguard Worker 			ret = asprintf(&name, "%s:%s", alias, op->name);
121*436bf2bcSAndroid Build Coastguard Worker 			if (ret < 0)
122*436bf2bcSAndroid Build Coastguard Worker 				goto err;
123*436bf2bcSAndroid Build Coastguard Worker 
124*436bf2bcSAndroid Build Coastguard Worker 			list = realloc(list, count + 2);
125*436bf2bcSAndroid Build Coastguard Worker 			if (!list) {
126*436bf2bcSAndroid Build Coastguard Worker 				list = temp;
127*436bf2bcSAndroid Build Coastguard Worker 				free(name);
128*436bf2bcSAndroid Build Coastguard Worker 				goto err;
129*436bf2bcSAndroid Build Coastguard Worker 			}
130*436bf2bcSAndroid Build Coastguard Worker 			list[count++] = name;
131*436bf2bcSAndroid Build Coastguard Worker 			list[count] = NULL;
132*436bf2bcSAndroid Build Coastguard Worker 		}
133*436bf2bcSAndroid Build Coastguard Worker 	}
134*436bf2bcSAndroid Build Coastguard Worker 	return list;
135*436bf2bcSAndroid Build Coastguard Worker 
136*436bf2bcSAndroid Build Coastguard Worker  err:
137*436bf2bcSAndroid Build Coastguard Worker 	while (--count >= 0)
138*436bf2bcSAndroid Build Coastguard Worker 		free(list[count]);
139*436bf2bcSAndroid Build Coastguard Worker 	free(list);
140*436bf2bcSAndroid Build Coastguard Worker 
141*436bf2bcSAndroid Build Coastguard Worker 	return INVALID_PLUGIN_LIST_OPTION;
142*436bf2bcSAndroid Build Coastguard Worker }
143*436bf2bcSAndroid Build Coastguard Worker 
tep_plugin_free_options_list(char ** list)144*436bf2bcSAndroid Build Coastguard Worker void tep_plugin_free_options_list(char **list)
145*436bf2bcSAndroid Build Coastguard Worker {
146*436bf2bcSAndroid Build Coastguard Worker 	int i;
147*436bf2bcSAndroid Build Coastguard Worker 
148*436bf2bcSAndroid Build Coastguard Worker 	if (!list)
149*436bf2bcSAndroid Build Coastguard Worker 		return;
150*436bf2bcSAndroid Build Coastguard Worker 
151*436bf2bcSAndroid Build Coastguard Worker 	if (list == INVALID_PLUGIN_LIST_OPTION)
152*436bf2bcSAndroid Build Coastguard Worker 		return;
153*436bf2bcSAndroid Build Coastguard Worker 
154*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; list[i]; i++)
155*436bf2bcSAndroid Build Coastguard Worker 		free(list[i]);
156*436bf2bcSAndroid Build Coastguard Worker 
157*436bf2bcSAndroid Build Coastguard Worker 	free(list);
158*436bf2bcSAndroid Build Coastguard Worker }
159*436bf2bcSAndroid Build Coastguard Worker 
160*436bf2bcSAndroid Build Coastguard Worker static int
update_option(const char * file,struct tep_plugin_option * option)161*436bf2bcSAndroid Build Coastguard Worker update_option(const char *file, struct tep_plugin_option *option)
162*436bf2bcSAndroid Build Coastguard Worker {
163*436bf2bcSAndroid Build Coastguard Worker 	struct trace_plugin_options *op;
164*436bf2bcSAndroid Build Coastguard Worker 	char *plugin;
165*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
166*436bf2bcSAndroid Build Coastguard Worker 
167*436bf2bcSAndroid Build Coastguard Worker 	if (option->plugin_alias) {
168*436bf2bcSAndroid Build Coastguard Worker 		plugin = strdup(option->plugin_alias);
169*436bf2bcSAndroid Build Coastguard Worker 		if (!plugin)
170*436bf2bcSAndroid Build Coastguard Worker 			return -1;
171*436bf2bcSAndroid Build Coastguard Worker 	} else {
172*436bf2bcSAndroid Build Coastguard Worker 		char *p;
173*436bf2bcSAndroid Build Coastguard Worker 		plugin = strdup(file);
174*436bf2bcSAndroid Build Coastguard Worker 		if (!plugin)
175*436bf2bcSAndroid Build Coastguard Worker 			return -1;
176*436bf2bcSAndroid Build Coastguard Worker 		p = strstr(plugin, ".");
177*436bf2bcSAndroid Build Coastguard Worker 		if (p)
178*436bf2bcSAndroid Build Coastguard Worker 			*p = '\0';
179*436bf2bcSAndroid Build Coastguard Worker 	}
180*436bf2bcSAndroid Build Coastguard Worker 
181*436bf2bcSAndroid Build Coastguard Worker 	/* first look for named options */
182*436bf2bcSAndroid Build Coastguard Worker 	for (op = trace_plugin_options; op; op = op->next) {
183*436bf2bcSAndroid Build Coastguard Worker 		if (!op->plugin)
184*436bf2bcSAndroid Build Coastguard Worker 			continue;
185*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(op->plugin, plugin) != 0)
186*436bf2bcSAndroid Build Coastguard Worker 			continue;
187*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(op->option, option->name) != 0)
188*436bf2bcSAndroid Build Coastguard Worker 			continue;
189*436bf2bcSAndroid Build Coastguard Worker 
190*436bf2bcSAndroid Build Coastguard Worker 		ret = update_option_value(option, op->value);
191*436bf2bcSAndroid Build Coastguard Worker 		if (ret)
192*436bf2bcSAndroid Build Coastguard Worker 			goto out;
193*436bf2bcSAndroid Build Coastguard Worker 		break;
194*436bf2bcSAndroid Build Coastguard Worker 	}
195*436bf2bcSAndroid Build Coastguard Worker 
196*436bf2bcSAndroid Build Coastguard Worker 	/* first look for unnamed options */
197*436bf2bcSAndroid Build Coastguard Worker 	for (op = trace_plugin_options; op; op = op->next) {
198*436bf2bcSAndroid Build Coastguard Worker 		if (op->plugin)
199*436bf2bcSAndroid Build Coastguard Worker 			continue;
200*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(op->option, option->name) != 0)
201*436bf2bcSAndroid Build Coastguard Worker 			continue;
202*436bf2bcSAndroid Build Coastguard Worker 
203*436bf2bcSAndroid Build Coastguard Worker 		ret = update_option_value(option, op->value);
204*436bf2bcSAndroid Build Coastguard Worker 		break;
205*436bf2bcSAndroid Build Coastguard Worker 	}
206*436bf2bcSAndroid Build Coastguard Worker 
207*436bf2bcSAndroid Build Coastguard Worker  out:
208*436bf2bcSAndroid Build Coastguard Worker 	free(plugin);
209*436bf2bcSAndroid Build Coastguard Worker 	return ret;
210*436bf2bcSAndroid Build Coastguard Worker }
211*436bf2bcSAndroid Build Coastguard Worker 
212*436bf2bcSAndroid Build Coastguard Worker /**
213*436bf2bcSAndroid Build Coastguard Worker  * tep_plugin_add_options - Add a set of options by a plugin
214*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the plugin adding the options
215*436bf2bcSAndroid Build Coastguard Worker  * @options: The set of options being loaded
216*436bf2bcSAndroid Build Coastguard Worker  *
217*436bf2bcSAndroid Build Coastguard Worker  * Sets the options with the values that have been added by user.
218*436bf2bcSAndroid Build Coastguard Worker  */
tep_plugin_add_options(const char * name,struct tep_plugin_option * options)219*436bf2bcSAndroid Build Coastguard Worker int tep_plugin_add_options(const char *name,
220*436bf2bcSAndroid Build Coastguard Worker 			   struct tep_plugin_option *options)
221*436bf2bcSAndroid Build Coastguard Worker {
222*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options *reg;
223*436bf2bcSAndroid Build Coastguard Worker 
224*436bf2bcSAndroid Build Coastguard Worker 	reg = malloc(sizeof(*reg));
225*436bf2bcSAndroid Build Coastguard Worker 	if (!reg)
226*436bf2bcSAndroid Build Coastguard Worker 		return -1;
227*436bf2bcSAndroid Build Coastguard Worker 	reg->next = registered_options;
228*436bf2bcSAndroid Build Coastguard Worker 	reg->options = options;
229*436bf2bcSAndroid Build Coastguard Worker 	registered_options = reg;
230*436bf2bcSAndroid Build Coastguard Worker 
231*436bf2bcSAndroid Build Coastguard Worker 	while (options->name) {
232*436bf2bcSAndroid Build Coastguard Worker 		update_option(name, options);
233*436bf2bcSAndroid Build Coastguard Worker 		options++;
234*436bf2bcSAndroid Build Coastguard Worker 	}
235*436bf2bcSAndroid Build Coastguard Worker 	return 0;
236*436bf2bcSAndroid Build Coastguard Worker }
237*436bf2bcSAndroid Build Coastguard Worker 
238*436bf2bcSAndroid Build Coastguard Worker /**
239*436bf2bcSAndroid Build Coastguard Worker  * tep_plugin_remove_options - remove plugin options that were registered
240*436bf2bcSAndroid Build Coastguard Worker  * @options: Options to removed that were registered with tep_plugin_add_options
241*436bf2bcSAndroid Build Coastguard Worker  */
tep_plugin_remove_options(struct tep_plugin_option * options)242*436bf2bcSAndroid Build Coastguard Worker void tep_plugin_remove_options(struct tep_plugin_option *options)
243*436bf2bcSAndroid Build Coastguard Worker {
244*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options **last;
245*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options *reg;
246*436bf2bcSAndroid Build Coastguard Worker 
247*436bf2bcSAndroid Build Coastguard Worker 	for (last = &registered_options; *last; last = &(*last)->next) {
248*436bf2bcSAndroid Build Coastguard Worker 		if ((*last)->options == options) {
249*436bf2bcSAndroid Build Coastguard Worker 			reg = *last;
250*436bf2bcSAndroid Build Coastguard Worker 			*last = reg->next;
251*436bf2bcSAndroid Build Coastguard Worker 			free(reg);
252*436bf2bcSAndroid Build Coastguard Worker 			return;
253*436bf2bcSAndroid Build Coastguard Worker 		}
254*436bf2bcSAndroid Build Coastguard Worker 	}
255*436bf2bcSAndroid Build Coastguard Worker }
256*436bf2bcSAndroid Build Coastguard Worker 
parse_option_name(char ** option,char ** plugin)257*436bf2bcSAndroid Build Coastguard Worker static int parse_option_name(char **option, char **plugin)
258*436bf2bcSAndroid Build Coastguard Worker {
259*436bf2bcSAndroid Build Coastguard Worker 	char *p;
260*436bf2bcSAndroid Build Coastguard Worker 
261*436bf2bcSAndroid Build Coastguard Worker 	*plugin = NULL;
262*436bf2bcSAndroid Build Coastguard Worker 
263*436bf2bcSAndroid Build Coastguard Worker 	if ((p = strstr(*option, ":"))) {
264*436bf2bcSAndroid Build Coastguard Worker 		*plugin = *option;
265*436bf2bcSAndroid Build Coastguard Worker 		*p = '\0';
266*436bf2bcSAndroid Build Coastguard Worker 		*option = strdup(p + 1);
267*436bf2bcSAndroid Build Coastguard Worker 		if (!*option)
268*436bf2bcSAndroid Build Coastguard Worker 			return -1;
269*436bf2bcSAndroid Build Coastguard Worker 	}
270*436bf2bcSAndroid Build Coastguard Worker 	return 0;
271*436bf2bcSAndroid Build Coastguard Worker }
272*436bf2bcSAndroid Build Coastguard Worker 
273*436bf2bcSAndroid Build Coastguard Worker static struct tep_plugin_option *
find_registered_option(const char * plugin,const char * option)274*436bf2bcSAndroid Build Coastguard Worker find_registered_option(const char *plugin, const char *option)
275*436bf2bcSAndroid Build Coastguard Worker {
276*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options *reg;
277*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_option *op;
278*436bf2bcSAndroid Build Coastguard Worker 	const char *op_plugin;
279*436bf2bcSAndroid Build Coastguard Worker 
280*436bf2bcSAndroid Build Coastguard Worker 	for (reg = registered_options; reg; reg = reg->next) {
281*436bf2bcSAndroid Build Coastguard Worker 		for (op = reg->options; op->name; op++) {
282*436bf2bcSAndroid Build Coastguard Worker 			if (op->plugin_alias)
283*436bf2bcSAndroid Build Coastguard Worker 				op_plugin = op->plugin_alias;
284*436bf2bcSAndroid Build Coastguard Worker 			else
285*436bf2bcSAndroid Build Coastguard Worker 				op_plugin = op->file;
286*436bf2bcSAndroid Build Coastguard Worker 
287*436bf2bcSAndroid Build Coastguard Worker 			if (plugin && strcmp(plugin, op_plugin) != 0)
288*436bf2bcSAndroid Build Coastguard Worker 				continue;
289*436bf2bcSAndroid Build Coastguard Worker 			if (strcmp(option, op->name) != 0)
290*436bf2bcSAndroid Build Coastguard Worker 				continue;
291*436bf2bcSAndroid Build Coastguard Worker 
292*436bf2bcSAndroid Build Coastguard Worker 			return op;
293*436bf2bcSAndroid Build Coastguard Worker 		}
294*436bf2bcSAndroid Build Coastguard Worker 	}
295*436bf2bcSAndroid Build Coastguard Worker 
296*436bf2bcSAndroid Build Coastguard Worker 	return NULL;
297*436bf2bcSAndroid Build Coastguard Worker }
298*436bf2bcSAndroid Build Coastguard Worker 
process_option(const char * plugin,const char * option,const char * val)299*436bf2bcSAndroid Build Coastguard Worker static int process_option(const char *plugin, const char *option, const char *val)
300*436bf2bcSAndroid Build Coastguard Worker {
301*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_option *op;
302*436bf2bcSAndroid Build Coastguard Worker 
303*436bf2bcSAndroid Build Coastguard Worker 	op = find_registered_option(plugin, option);
304*436bf2bcSAndroid Build Coastguard Worker 	if (!op)
305*436bf2bcSAndroid Build Coastguard Worker 		return 0;
306*436bf2bcSAndroid Build Coastguard Worker 
307*436bf2bcSAndroid Build Coastguard Worker 	return update_option_value(op, val);
308*436bf2bcSAndroid Build Coastguard Worker }
309*436bf2bcSAndroid Build Coastguard Worker 
310*436bf2bcSAndroid Build Coastguard Worker /**
311*436bf2bcSAndroid Build Coastguard Worker  * tep_plugin_add_option - add an option/val pair to set plugin options
312*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the option (format: <plugin>:<option> or just <option>)
313*436bf2bcSAndroid Build Coastguard Worker  * @val: (optional) the value for the option
314*436bf2bcSAndroid Build Coastguard Worker  *
315*436bf2bcSAndroid Build Coastguard Worker  * Modify a plugin option. If @val is given than the value of the option
316*436bf2bcSAndroid Build Coastguard Worker  * is set (note, some options just take a boolean, so @val must be either
317*436bf2bcSAndroid Build Coastguard Worker  * "1" or "0" or "true" or "false").
318*436bf2bcSAndroid Build Coastguard Worker  */
tep_plugin_add_option(const char * name,const char * val)319*436bf2bcSAndroid Build Coastguard Worker int tep_plugin_add_option(const char *name, const char *val)
320*436bf2bcSAndroid Build Coastguard Worker {
321*436bf2bcSAndroid Build Coastguard Worker 	struct trace_plugin_options *op;
322*436bf2bcSAndroid Build Coastguard Worker 	char *option_str;
323*436bf2bcSAndroid Build Coastguard Worker 	char *plugin;
324*436bf2bcSAndroid Build Coastguard Worker 
325*436bf2bcSAndroid Build Coastguard Worker 	option_str = strdup(name);
326*436bf2bcSAndroid Build Coastguard Worker 	if (!option_str)
327*436bf2bcSAndroid Build Coastguard Worker 		return -ENOMEM;
328*436bf2bcSAndroid Build Coastguard Worker 
329*436bf2bcSAndroid Build Coastguard Worker 	if (parse_option_name(&option_str, &plugin) < 0)
330*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
331*436bf2bcSAndroid Build Coastguard Worker 
332*436bf2bcSAndroid Build Coastguard Worker 	/* If the option exists, update the val */
333*436bf2bcSAndroid Build Coastguard Worker 	for (op = trace_plugin_options; op; op = op->next) {
334*436bf2bcSAndroid Build Coastguard Worker 		/* Both must be NULL or not NULL */
335*436bf2bcSAndroid Build Coastguard Worker 		if ((!plugin || !op->plugin) && plugin != op->plugin)
336*436bf2bcSAndroid Build Coastguard Worker 			continue;
337*436bf2bcSAndroid Build Coastguard Worker 		if (plugin && strcmp(plugin, op->plugin) != 0)
338*436bf2bcSAndroid Build Coastguard Worker 			continue;
339*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(op->option, option_str) != 0)
340*436bf2bcSAndroid Build Coastguard Worker 			continue;
341*436bf2bcSAndroid Build Coastguard Worker 
342*436bf2bcSAndroid Build Coastguard Worker 		/* update option */
343*436bf2bcSAndroid Build Coastguard Worker 		free(op->value);
344*436bf2bcSAndroid Build Coastguard Worker 		if (val) {
345*436bf2bcSAndroid Build Coastguard Worker 			op->value = strdup(val);
346*436bf2bcSAndroid Build Coastguard Worker 			if (!op->value)
347*436bf2bcSAndroid Build Coastguard Worker 				goto out_free;
348*436bf2bcSAndroid Build Coastguard Worker 		} else
349*436bf2bcSAndroid Build Coastguard Worker 			op->value = NULL;
350*436bf2bcSAndroid Build Coastguard Worker 
351*436bf2bcSAndroid Build Coastguard Worker 		/* plugin and option_str don't get freed at the end */
352*436bf2bcSAndroid Build Coastguard Worker 		free(plugin);
353*436bf2bcSAndroid Build Coastguard Worker 		free(option_str);
354*436bf2bcSAndroid Build Coastguard Worker 
355*436bf2bcSAndroid Build Coastguard Worker 		plugin = op->plugin;
356*436bf2bcSAndroid Build Coastguard Worker 		option_str = op->option;
357*436bf2bcSAndroid Build Coastguard Worker 		break;
358*436bf2bcSAndroid Build Coastguard Worker 	}
359*436bf2bcSAndroid Build Coastguard Worker 
360*436bf2bcSAndroid Build Coastguard Worker 	/* If not found, create */
361*436bf2bcSAndroid Build Coastguard Worker 	if (!op) {
362*436bf2bcSAndroid Build Coastguard Worker 		op = malloc(sizeof(*op));
363*436bf2bcSAndroid Build Coastguard Worker 		if (!op)
364*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
365*436bf2bcSAndroid Build Coastguard Worker 		memset(op, 0, sizeof(*op));
366*436bf2bcSAndroid Build Coastguard Worker 		op->plugin = plugin;
367*436bf2bcSAndroid Build Coastguard Worker 		op->option = option_str;
368*436bf2bcSAndroid Build Coastguard Worker 		if (val) {
369*436bf2bcSAndroid Build Coastguard Worker 			op->value = strdup(val);
370*436bf2bcSAndroid Build Coastguard Worker 			if (!op->value) {
371*436bf2bcSAndroid Build Coastguard Worker 				free(op);
372*436bf2bcSAndroid Build Coastguard Worker 				goto out_free;
373*436bf2bcSAndroid Build Coastguard Worker 			}
374*436bf2bcSAndroid Build Coastguard Worker 		}
375*436bf2bcSAndroid Build Coastguard Worker 		op->next = trace_plugin_options;
376*436bf2bcSAndroid Build Coastguard Worker 		trace_plugin_options = op;
377*436bf2bcSAndroid Build Coastguard Worker 	}
378*436bf2bcSAndroid Build Coastguard Worker 
379*436bf2bcSAndroid Build Coastguard Worker 	return process_option(plugin, option_str, val);
380*436bf2bcSAndroid Build Coastguard Worker 
381*436bf2bcSAndroid Build Coastguard Worker out_free:
382*436bf2bcSAndroid Build Coastguard Worker 	free(plugin);
383*436bf2bcSAndroid Build Coastguard Worker 	free(option_str);
384*436bf2bcSAndroid Build Coastguard Worker 	return -ENOMEM;
385*436bf2bcSAndroid Build Coastguard Worker }
386*436bf2bcSAndroid Build Coastguard Worker 
print_op_data(struct trace_seq * s,const char * name,const char * op)387*436bf2bcSAndroid Build Coastguard Worker static void print_op_data(struct trace_seq *s, const char *name,
388*436bf2bcSAndroid Build Coastguard Worker 			  const char *op)
389*436bf2bcSAndroid Build Coastguard Worker {
390*436bf2bcSAndroid Build Coastguard Worker 	if (op)
391*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%8s:\t%s\n", name, op);
392*436bf2bcSAndroid Build Coastguard Worker }
393*436bf2bcSAndroid Build Coastguard Worker 
394*436bf2bcSAndroid Build Coastguard Worker /**
395*436bf2bcSAndroid Build Coastguard Worker  * tep_plugin_print_options - print out the registered plugin options
396*436bf2bcSAndroid Build Coastguard Worker  * @s: The trace_seq descriptor to write the plugin options into
397*436bf2bcSAndroid Build Coastguard Worker  *
398*436bf2bcSAndroid Build Coastguard Worker  * Writes a list of options into trace_seq @s.
399*436bf2bcSAndroid Build Coastguard Worker  */
tep_plugin_print_options(struct trace_seq * s)400*436bf2bcSAndroid Build Coastguard Worker void tep_plugin_print_options(struct trace_seq *s)
401*436bf2bcSAndroid Build Coastguard Worker {
402*436bf2bcSAndroid Build Coastguard Worker 	struct registered_plugin_options *reg;
403*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_option *op;
404*436bf2bcSAndroid Build Coastguard Worker 
405*436bf2bcSAndroid Build Coastguard Worker 	for (reg = registered_options; reg; reg = reg->next) {
406*436bf2bcSAndroid Build Coastguard Worker 		if (reg != registered_options)
407*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "============\n");
408*436bf2bcSAndroid Build Coastguard Worker 		for (op = reg->options; op->name; op++) {
409*436bf2bcSAndroid Build Coastguard Worker 			if (op != reg->options)
410*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "------------\n");
411*436bf2bcSAndroid Build Coastguard Worker 			print_op_data(s, "file", op->file);
412*436bf2bcSAndroid Build Coastguard Worker 			print_op_data(s, "plugin", op->plugin_alias);
413*436bf2bcSAndroid Build Coastguard Worker 			print_op_data(s, "option", op->name);
414*436bf2bcSAndroid Build Coastguard Worker 			print_op_data(s, "desc", op->description);
415*436bf2bcSAndroid Build Coastguard Worker 			print_op_data(s, "value", op->value);
416*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "%8s:\t%d\n", "set", op->set);
417*436bf2bcSAndroid Build Coastguard Worker 		}
418*436bf2bcSAndroid Build Coastguard Worker 	}
419*436bf2bcSAndroid Build Coastguard Worker }
420*436bf2bcSAndroid Build Coastguard Worker 
421*436bf2bcSAndroid Build Coastguard Worker /**
422*436bf2bcSAndroid Build Coastguard Worker  * tep_print_plugins - print out the list of plugins loaded
423*436bf2bcSAndroid Build Coastguard Worker  * @s: the trace_seq descripter to write to
424*436bf2bcSAndroid Build Coastguard Worker  * @prefix: The prefix string to add before listing the option name
425*436bf2bcSAndroid Build Coastguard Worker  * @suffix: The suffix string ot append after the option name
426*436bf2bcSAndroid Build Coastguard Worker  * @list: The list of plugins (usually returned by tep_load_plugins()
427*436bf2bcSAndroid Build Coastguard Worker  *
428*436bf2bcSAndroid Build Coastguard Worker  * Writes to the trace_seq @s the list of plugins (files) that is
429*436bf2bcSAndroid Build Coastguard Worker  * returned by tep_load_plugins(). Use @prefix and @suffix for formating:
430*436bf2bcSAndroid Build Coastguard Worker  * @prefix = "  ", @suffix = "\n".
431*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_plugins(struct trace_seq * s,const char * prefix,const char * suffix,const struct tep_plugin_list * list)432*436bf2bcSAndroid Build Coastguard Worker void tep_print_plugins(struct trace_seq *s,
433*436bf2bcSAndroid Build Coastguard Worker 		       const char *prefix, const char *suffix,
434*436bf2bcSAndroid Build Coastguard Worker 		       const struct tep_plugin_list *list)
435*436bf2bcSAndroid Build Coastguard Worker {
436*436bf2bcSAndroid Build Coastguard Worker 	while (list) {
437*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix);
438*436bf2bcSAndroid Build Coastguard Worker 		list = list->next;
439*436bf2bcSAndroid Build Coastguard Worker 	}
440*436bf2bcSAndroid Build Coastguard Worker }
441*436bf2bcSAndroid Build Coastguard Worker 
442*436bf2bcSAndroid Build Coastguard Worker static void
load_plugin(struct tep_handle * tep,const char * path,const char * file,void * data)443*436bf2bcSAndroid Build Coastguard Worker load_plugin(struct tep_handle *tep, const char *path,
444*436bf2bcSAndroid Build Coastguard Worker 	    const char *file, void *data)
445*436bf2bcSAndroid Build Coastguard Worker {
446*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_list **plugin_list = data;
447*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_option *options;
448*436bf2bcSAndroid Build Coastguard Worker 	tep_plugin_load_func func;
449*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_list *list;
450*436bf2bcSAndroid Build Coastguard Worker 	const char *alias;
451*436bf2bcSAndroid Build Coastguard Worker 	char *plugin;
452*436bf2bcSAndroid Build Coastguard Worker 	void *handle;
453*436bf2bcSAndroid Build Coastguard Worker 	int ret;
454*436bf2bcSAndroid Build Coastguard Worker 
455*436bf2bcSAndroid Build Coastguard Worker 	ret = asprintf(&plugin, "%s/%s", path, file);
456*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0) {
457*436bf2bcSAndroid Build Coastguard Worker 		tep_warning("could not allocate plugin memory\n");
458*436bf2bcSAndroid Build Coastguard Worker 		return;
459*436bf2bcSAndroid Build Coastguard Worker 	}
460*436bf2bcSAndroid Build Coastguard Worker 
461*436bf2bcSAndroid Build Coastguard Worker 	handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
462*436bf2bcSAndroid Build Coastguard Worker 	if (!handle) {
463*436bf2bcSAndroid Build Coastguard Worker 		tep_warning("could not load plugin '%s'\n%s\n",
464*436bf2bcSAndroid Build Coastguard Worker 			    plugin, dlerror());
465*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
466*436bf2bcSAndroid Build Coastguard Worker 	}
467*436bf2bcSAndroid Build Coastguard Worker 
468*436bf2bcSAndroid Build Coastguard Worker 	alias = dlsym(handle, TEP_PLUGIN_ALIAS_NAME);
469*436bf2bcSAndroid Build Coastguard Worker 	if (!alias)
470*436bf2bcSAndroid Build Coastguard Worker 		alias = file;
471*436bf2bcSAndroid Build Coastguard Worker 
472*436bf2bcSAndroid Build Coastguard Worker 	options = dlsym(handle, TEP_PLUGIN_OPTIONS_NAME);
473*436bf2bcSAndroid Build Coastguard Worker 	if (options) {
474*436bf2bcSAndroid Build Coastguard Worker 		while (options->name) {
475*436bf2bcSAndroid Build Coastguard Worker 			ret = update_option(alias, options);
476*436bf2bcSAndroid Build Coastguard Worker 			if (ret < 0)
477*436bf2bcSAndroid Build Coastguard Worker 				goto out_close;
478*436bf2bcSAndroid Build Coastguard Worker 			options++;
479*436bf2bcSAndroid Build Coastguard Worker 		}
480*436bf2bcSAndroid Build Coastguard Worker 	}
481*436bf2bcSAndroid Build Coastguard Worker 
482*436bf2bcSAndroid Build Coastguard Worker 	func = dlsym(handle, TEP_PLUGIN_LOADER_NAME);
483*436bf2bcSAndroid Build Coastguard Worker 	if (!func) {
484*436bf2bcSAndroid Build Coastguard Worker 		tep_warning("could not find func '%s' in plugin '%s'\n%s\n",
485*436bf2bcSAndroid Build Coastguard Worker 			    TEP_PLUGIN_LOADER_NAME, plugin, dlerror());
486*436bf2bcSAndroid Build Coastguard Worker 		goto out_close;
487*436bf2bcSAndroid Build Coastguard Worker 	}
488*436bf2bcSAndroid Build Coastguard Worker 
489*436bf2bcSAndroid Build Coastguard Worker 	list = malloc(sizeof(*list));
490*436bf2bcSAndroid Build Coastguard Worker 	if (!list) {
491*436bf2bcSAndroid Build Coastguard Worker 		tep_warning("could not allocate plugin memory\n");
492*436bf2bcSAndroid Build Coastguard Worker 		goto out_close;
493*436bf2bcSAndroid Build Coastguard Worker 	}
494*436bf2bcSAndroid Build Coastguard Worker 
495*436bf2bcSAndroid Build Coastguard Worker 	list->next = *plugin_list;
496*436bf2bcSAndroid Build Coastguard Worker 	list->handle = handle;
497*436bf2bcSAndroid Build Coastguard Worker 	list->name = plugin;
498*436bf2bcSAndroid Build Coastguard Worker 	*plugin_list = list;
499*436bf2bcSAndroid Build Coastguard Worker 
500*436bf2bcSAndroid Build Coastguard Worker 	tep_info("registering plugin: %s", plugin);
501*436bf2bcSAndroid Build Coastguard Worker 	func(tep);
502*436bf2bcSAndroid Build Coastguard Worker 	return;
503*436bf2bcSAndroid Build Coastguard Worker 
504*436bf2bcSAndroid Build Coastguard Worker out_close:
505*436bf2bcSAndroid Build Coastguard Worker 	dlclose(handle);
506*436bf2bcSAndroid Build Coastguard Worker  out_free:
507*436bf2bcSAndroid Build Coastguard Worker 	free(plugin);
508*436bf2bcSAndroid Build Coastguard Worker }
509*436bf2bcSAndroid Build Coastguard Worker 
510*436bf2bcSAndroid Build Coastguard Worker static void
load_plugins_dir(struct tep_handle * tep,const char * suffix,const char * path,void (* load_plugin)(struct tep_handle * tep,const char * path,const char * name,void * data),void * data)511*436bf2bcSAndroid Build Coastguard Worker load_plugins_dir(struct tep_handle *tep, const char *suffix,
512*436bf2bcSAndroid Build Coastguard Worker 		 const char *path,
513*436bf2bcSAndroid Build Coastguard Worker 		 void (*load_plugin)(struct tep_handle *tep,
514*436bf2bcSAndroid Build Coastguard Worker 				     const char *path,
515*436bf2bcSAndroid Build Coastguard Worker 				     const char *name,
516*436bf2bcSAndroid Build Coastguard Worker 				     void *data),
517*436bf2bcSAndroid Build Coastguard Worker 		 void *data)
518*436bf2bcSAndroid Build Coastguard Worker {
519*436bf2bcSAndroid Build Coastguard Worker 	struct dirent *dent;
520*436bf2bcSAndroid Build Coastguard Worker 	struct stat st;
521*436bf2bcSAndroid Build Coastguard Worker 	DIR *dir;
522*436bf2bcSAndroid Build Coastguard Worker 	int ret;
523*436bf2bcSAndroid Build Coastguard Worker 
524*436bf2bcSAndroid Build Coastguard Worker 	ret = stat(path, &st);
525*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0)
526*436bf2bcSAndroid Build Coastguard Worker 		return;
527*436bf2bcSAndroid Build Coastguard Worker 
528*436bf2bcSAndroid Build Coastguard Worker 	if (!S_ISDIR(st.st_mode))
529*436bf2bcSAndroid Build Coastguard Worker 		return;
530*436bf2bcSAndroid Build Coastguard Worker 
531*436bf2bcSAndroid Build Coastguard Worker 	dir = opendir(path);
532*436bf2bcSAndroid Build Coastguard Worker 	if (!dir)
533*436bf2bcSAndroid Build Coastguard Worker 		return;
534*436bf2bcSAndroid Build Coastguard Worker 
535*436bf2bcSAndroid Build Coastguard Worker 	while ((dent = readdir(dir))) {
536*436bf2bcSAndroid Build Coastguard Worker 		const char *name = dent->d_name;
537*436bf2bcSAndroid Build Coastguard Worker 
538*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(name, ".") == 0 ||
539*436bf2bcSAndroid Build Coastguard Worker 		    strcmp(name, "..") == 0)
540*436bf2bcSAndroid Build Coastguard Worker 			continue;
541*436bf2bcSAndroid Build Coastguard Worker 
542*436bf2bcSAndroid Build Coastguard Worker 		/* Only load plugins that end in suffix */
543*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
544*436bf2bcSAndroid Build Coastguard Worker 			continue;
545*436bf2bcSAndroid Build Coastguard Worker 
546*436bf2bcSAndroid Build Coastguard Worker 		load_plugin(tep, path, name, data);
547*436bf2bcSAndroid Build Coastguard Worker 	}
548*436bf2bcSAndroid Build Coastguard Worker 
549*436bf2bcSAndroid Build Coastguard Worker 	closedir(dir);
550*436bf2bcSAndroid Build Coastguard Worker }
551*436bf2bcSAndroid Build Coastguard Worker 
552*436bf2bcSAndroid Build Coastguard Worker /**
553*436bf2bcSAndroid Build Coastguard Worker  * tep_load_plugins_hook - call a user specified callback to load a plugin
554*436bf2bcSAndroid Build Coastguard Worker  * @tep: handler to traceevent context
555*436bf2bcSAndroid Build Coastguard Worker  * @suffix: filter only plugin files with given suffix
556*436bf2bcSAndroid Build Coastguard Worker  * @load_plugin: user specified callback, called for each plugin file
557*436bf2bcSAndroid Build Coastguard Worker  * @data: custom context, passed to @load_plugin
558*436bf2bcSAndroid Build Coastguard Worker  *
559*436bf2bcSAndroid Build Coastguard Worker  * Searches for traceevent plugin files and calls @load_plugin for each
560*436bf2bcSAndroid Build Coastguard Worker  * The order of plugins search is:
561*436bf2bcSAndroid Build Coastguard Worker  *  - Directories, specified in @tep->plugins_dir and priority TEP_PLUGIN_FIRST
562*436bf2bcSAndroid Build Coastguard Worker  *  - Directory, specified at compile time with PLUGIN_TRACEEVENT_DIR
563*436bf2bcSAndroid Build Coastguard Worker  *  - Directory, specified by environment variable TRACEEVENT_PLUGIN_DIR
564*436bf2bcSAndroid Build Coastguard Worker  *  - In user's home: ~/.local/lib/traceevent/plugins/
565*436bf2bcSAndroid Build Coastguard Worker  *  - Directories, specified in @tep->plugins_dir and priority TEP_PLUGIN_LAST
566*436bf2bcSAndroid Build Coastguard Worker  *
567*436bf2bcSAndroid Build Coastguard Worker  */
tep_load_plugins_hook(struct tep_handle * tep,const char * suffix,void (* load_plugin)(struct tep_handle * tep,const char * path,const char * name,void * data),void * data)568*436bf2bcSAndroid Build Coastguard Worker void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix,
569*436bf2bcSAndroid Build Coastguard Worker 			   void (*load_plugin)(struct tep_handle *tep,
570*436bf2bcSAndroid Build Coastguard Worker 					       const char *path,
571*436bf2bcSAndroid Build Coastguard Worker 					       const char *name,
572*436bf2bcSAndroid Build Coastguard Worker 					       void *data),
573*436bf2bcSAndroid Build Coastguard Worker 			   void *data)
574*436bf2bcSAndroid Build Coastguard Worker {
575*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugins_dir *dir = NULL;
576*436bf2bcSAndroid Build Coastguard Worker 	char *home;
577*436bf2bcSAndroid Build Coastguard Worker 	char *path;
578*436bf2bcSAndroid Build Coastguard Worker 	char *envdir;
579*436bf2bcSAndroid Build Coastguard Worker 	int ret;
580*436bf2bcSAndroid Build Coastguard Worker 
581*436bf2bcSAndroid Build Coastguard Worker 	if (tep && tep->flags & TEP_DISABLE_PLUGINS)
582*436bf2bcSAndroid Build Coastguard Worker 		return;
583*436bf2bcSAndroid Build Coastguard Worker 
584*436bf2bcSAndroid Build Coastguard Worker 	if (tep)
585*436bf2bcSAndroid Build Coastguard Worker 		dir = tep->plugins_dir;
586*436bf2bcSAndroid Build Coastguard Worker 	while (dir) {
587*436bf2bcSAndroid Build Coastguard Worker 		if (dir->prio == TEP_PLUGIN_FIRST)
588*436bf2bcSAndroid Build Coastguard Worker 			load_plugins_dir(tep, suffix, dir->path,
589*436bf2bcSAndroid Build Coastguard Worker 					 load_plugin, data);
590*436bf2bcSAndroid Build Coastguard Worker 		dir = dir->next;
591*436bf2bcSAndroid Build Coastguard Worker 	}
592*436bf2bcSAndroid Build Coastguard Worker 
593*436bf2bcSAndroid Build Coastguard Worker 	/*
594*436bf2bcSAndroid Build Coastguard Worker 	 * If a system plugin directory was defined,
595*436bf2bcSAndroid Build Coastguard Worker 	 * check that first.
596*436bf2bcSAndroid Build Coastguard Worker 	 */
597*436bf2bcSAndroid Build Coastguard Worker #ifdef PLUGIN_DIR
598*436bf2bcSAndroid Build Coastguard Worker 	if (!tep || !(tep->flags & TEP_DISABLE_SYS_PLUGINS))
599*436bf2bcSAndroid Build Coastguard Worker 		load_plugins_dir(tep, suffix, PLUGIN_DIR,
600*436bf2bcSAndroid Build Coastguard Worker 				 load_plugin, data);
601*436bf2bcSAndroid Build Coastguard Worker #endif
602*436bf2bcSAndroid Build Coastguard Worker 
603*436bf2bcSAndroid Build Coastguard Worker 	/*
604*436bf2bcSAndroid Build Coastguard Worker 	 * Next let the environment-set plugin directory
605*436bf2bcSAndroid Build Coastguard Worker 	 * override the system defaults.
606*436bf2bcSAndroid Build Coastguard Worker 	 */
607*436bf2bcSAndroid Build Coastguard Worker 	envdir = getenv("TRACEEVENT_PLUGIN_DIR");
608*436bf2bcSAndroid Build Coastguard Worker 	if (envdir)
609*436bf2bcSAndroid Build Coastguard Worker 		load_plugins_dir(tep, suffix, envdir, load_plugin, data);
610*436bf2bcSAndroid Build Coastguard Worker 
611*436bf2bcSAndroid Build Coastguard Worker 	/*
612*436bf2bcSAndroid Build Coastguard Worker 	 * Now let the home directory override the environment
613*436bf2bcSAndroid Build Coastguard Worker 	 * or system defaults.
614*436bf2bcSAndroid Build Coastguard Worker 	 */
615*436bf2bcSAndroid Build Coastguard Worker 	home = getenv("HOME");
616*436bf2bcSAndroid Build Coastguard Worker 	if (!home)
617*436bf2bcSAndroid Build Coastguard Worker 		return;
618*436bf2bcSAndroid Build Coastguard Worker 
619*436bf2bcSAndroid Build Coastguard Worker 	ret = asprintf(&path, "%s/%s", home, LOCAL_PLUGIN_DIR);
620*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0) {
621*436bf2bcSAndroid Build Coastguard Worker 		tep_warning("could not allocate plugin memory\n");
622*436bf2bcSAndroid Build Coastguard Worker 		return;
623*436bf2bcSAndroid Build Coastguard Worker 	}
624*436bf2bcSAndroid Build Coastguard Worker 
625*436bf2bcSAndroid Build Coastguard Worker 	load_plugins_dir(tep, suffix, path, load_plugin, data);
626*436bf2bcSAndroid Build Coastguard Worker 
627*436bf2bcSAndroid Build Coastguard Worker 	if (tep)
628*436bf2bcSAndroid Build Coastguard Worker 		dir = tep->plugins_dir;
629*436bf2bcSAndroid Build Coastguard Worker 	while (dir) {
630*436bf2bcSAndroid Build Coastguard Worker 		if (dir->prio == TEP_PLUGIN_LAST)
631*436bf2bcSAndroid Build Coastguard Worker 			load_plugins_dir(tep, suffix, dir->path,
632*436bf2bcSAndroid Build Coastguard Worker 					 load_plugin, data);
633*436bf2bcSAndroid Build Coastguard Worker 		dir = dir->next;
634*436bf2bcSAndroid Build Coastguard Worker 	}
635*436bf2bcSAndroid Build Coastguard Worker 
636*436bf2bcSAndroid Build Coastguard Worker 	free(path);
637*436bf2bcSAndroid Build Coastguard Worker }
638*436bf2bcSAndroid Build Coastguard Worker 
639*436bf2bcSAndroid Build Coastguard Worker struct tep_plugin_list*
tep_load_plugins(struct tep_handle * tep)640*436bf2bcSAndroid Build Coastguard Worker tep_load_plugins(struct tep_handle *tep)
641*436bf2bcSAndroid Build Coastguard Worker {
642*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_list *list = NULL;
643*436bf2bcSAndroid Build Coastguard Worker 
644*436bf2bcSAndroid Build Coastguard Worker 	tep_load_plugins_hook(tep, ".so", load_plugin, &list);
645*436bf2bcSAndroid Build Coastguard Worker 	return list;
646*436bf2bcSAndroid Build Coastguard Worker }
647*436bf2bcSAndroid Build Coastguard Worker 
648*436bf2bcSAndroid Build Coastguard Worker /**
649*436bf2bcSAndroid Build Coastguard Worker  * tep_add_plugin_path - Add a new plugin directory.
650*436bf2bcSAndroid Build Coastguard Worker  * @tep: Trace event handler.
651*436bf2bcSAndroid Build Coastguard Worker  * @path: Path to a directory. All plugin files in that
652*436bf2bcSAndroid Build Coastguard Worker  *	  directory will be loaded.
653*436bf2bcSAndroid Build Coastguard Worker  *@prio: Load priority of the plugins in that directory.
654*436bf2bcSAndroid Build Coastguard Worker  *
655*436bf2bcSAndroid Build Coastguard Worker  * Returns -1 in case of an error, 0 otherwise.
656*436bf2bcSAndroid Build Coastguard Worker  */
tep_add_plugin_path(struct tep_handle * tep,char * path,enum tep_plugin_load_priority prio)657*436bf2bcSAndroid Build Coastguard Worker int tep_add_plugin_path(struct tep_handle *tep, char *path,
658*436bf2bcSAndroid Build Coastguard Worker 			enum tep_plugin_load_priority prio)
659*436bf2bcSAndroid Build Coastguard Worker {
660*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugins_dir *dir;
661*436bf2bcSAndroid Build Coastguard Worker 
662*436bf2bcSAndroid Build Coastguard Worker 	if (!tep || !path)
663*436bf2bcSAndroid Build Coastguard Worker 		return -1;
664*436bf2bcSAndroid Build Coastguard Worker 
665*436bf2bcSAndroid Build Coastguard Worker 	dir = calloc(1, sizeof(*dir));
666*436bf2bcSAndroid Build Coastguard Worker 	if (!dir)
667*436bf2bcSAndroid Build Coastguard Worker 		return -1;
668*436bf2bcSAndroid Build Coastguard Worker 
669*436bf2bcSAndroid Build Coastguard Worker 	dir->path = strdup(path);
670*436bf2bcSAndroid Build Coastguard Worker 	if (!dir->path) {
671*436bf2bcSAndroid Build Coastguard Worker 		free(dir);
672*436bf2bcSAndroid Build Coastguard Worker 		return -1;
673*436bf2bcSAndroid Build Coastguard Worker 	}
674*436bf2bcSAndroid Build Coastguard Worker 	dir->prio = prio;
675*436bf2bcSAndroid Build Coastguard Worker 	dir->next = tep->plugins_dir;
676*436bf2bcSAndroid Build Coastguard Worker 	tep->plugins_dir = dir;
677*436bf2bcSAndroid Build Coastguard Worker 
678*436bf2bcSAndroid Build Coastguard Worker 	return 0;
679*436bf2bcSAndroid Build Coastguard Worker }
680*436bf2bcSAndroid Build Coastguard Worker 
free_tep_plugin_paths(struct tep_handle * tep)681*436bf2bcSAndroid Build Coastguard Worker __hidden void free_tep_plugin_paths(struct tep_handle *tep)
682*436bf2bcSAndroid Build Coastguard Worker {
683*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugins_dir *dir;
684*436bf2bcSAndroid Build Coastguard Worker 
685*436bf2bcSAndroid Build Coastguard Worker 	if (!tep)
686*436bf2bcSAndroid Build Coastguard Worker 		return;
687*436bf2bcSAndroid Build Coastguard Worker 
688*436bf2bcSAndroid Build Coastguard Worker 	dir = tep->plugins_dir;
689*436bf2bcSAndroid Build Coastguard Worker 	while (dir) {
690*436bf2bcSAndroid Build Coastguard Worker 		tep->plugins_dir = tep->plugins_dir->next;
691*436bf2bcSAndroid Build Coastguard Worker 		free(dir->path);
692*436bf2bcSAndroid Build Coastguard Worker 		free(dir);
693*436bf2bcSAndroid Build Coastguard Worker 		dir = tep->plugins_dir;
694*436bf2bcSAndroid Build Coastguard Worker 	}
695*436bf2bcSAndroid Build Coastguard Worker }
696*436bf2bcSAndroid Build Coastguard Worker 
697*436bf2bcSAndroid Build Coastguard Worker void
tep_unload_plugins(struct tep_plugin_list * plugin_list,struct tep_handle * tep)698*436bf2bcSAndroid Build Coastguard Worker tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep)
699*436bf2bcSAndroid Build Coastguard Worker {
700*436bf2bcSAndroid Build Coastguard Worker 	tep_plugin_unload_func func;
701*436bf2bcSAndroid Build Coastguard Worker 	struct tep_plugin_list *list;
702*436bf2bcSAndroid Build Coastguard Worker 
703*436bf2bcSAndroid Build Coastguard Worker 	while (plugin_list) {
704*436bf2bcSAndroid Build Coastguard Worker 		list = plugin_list;
705*436bf2bcSAndroid Build Coastguard Worker 		plugin_list = list->next;
706*436bf2bcSAndroid Build Coastguard Worker 		func = dlsym(list->handle, TEP_PLUGIN_UNLOADER_NAME);
707*436bf2bcSAndroid Build Coastguard Worker 		if (func)
708*436bf2bcSAndroid Build Coastguard Worker 			func(tep);
709*436bf2bcSAndroid Build Coastguard Worker 		dlclose(list->handle);
710*436bf2bcSAndroid Build Coastguard Worker 		free(list->name);
711*436bf2bcSAndroid Build Coastguard Worker 		free(list);
712*436bf2bcSAndroid Build Coastguard Worker 	}
713*436bf2bcSAndroid Build Coastguard Worker }
714