perf scripting: Avoid leaking the scripting_context variable
[pandora-kernel.git] / tools / perf / util / exec_cmd.c
1 #include "cache.h"
2 #include "exec_cmd.h"
3 #include "quote.h"
4
5 #include <string.h>
6
7 #define MAX_ARGS        32
8
9 static const char *argv_exec_path;
10 static const char *argv0_path;
11
12 const char *system_path(const char *path)
13 {
14         static const char *prefix = PREFIX;
15         struct strbuf d = STRBUF_INIT;
16
17         if (is_absolute_path(path))
18                 return path;
19
20         strbuf_addf(&d, "%s/%s", prefix, path);
21         path = strbuf_detach(&d, NULL);
22         return path;
23 }
24
25 const char *perf_extract_argv0_path(const char *argv0)
26 {
27         const char *slash;
28
29         if (!argv0 || !*argv0)
30                 return NULL;
31         slash = argv0 + strlen(argv0);
32
33         while (argv0 <= slash && !is_dir_sep(*slash))
34                 slash--;
35
36         if (slash >= argv0) {
37                 argv0_path = strndup(argv0, slash - argv0);
38                 return argv0_path ? slash + 1 : NULL;
39         }
40
41         return argv0;
42 }
43
44 void perf_set_argv_exec_path(const char *exec_path)
45 {
46         argv_exec_path = exec_path;
47         /*
48          * Propagate this setting to external programs.
49          */
50         setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
51 }
52
53
54 /* Returns the highest-priority, location to look for perf programs. */
55 const char *perf_exec_path(void)
56 {
57         const char *env;
58
59         if (argv_exec_path)
60                 return argv_exec_path;
61
62         env = getenv(EXEC_PATH_ENVIRONMENT);
63         if (env && *env) {
64                 return env;
65         }
66
67         return system_path(PERF_EXEC_PATH);
68 }
69
70 static void add_path(struct strbuf *out, const char *path)
71 {
72         if (path && *path) {
73                 if (is_absolute_path(path))
74                         strbuf_addstr(out, path);
75                 else
76                         strbuf_addstr(out, make_nonrelative_path(path));
77
78                 strbuf_addch(out, PATH_SEP);
79         }
80 }
81
82 void setup_path(void)
83 {
84         const char *old_path = getenv("PATH");
85         struct strbuf new_path = STRBUF_INIT;
86
87         add_path(&new_path, perf_exec_path());
88         add_path(&new_path, argv0_path);
89
90         if (old_path)
91                 strbuf_addstr(&new_path, old_path);
92         else
93                 strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
94
95         setenv("PATH", new_path.buf, 1);
96
97         strbuf_release(&new_path);
98 }
99
100 static const char **prepare_perf_cmd(const char **argv)
101 {
102         int argc;
103         const char **nargv;
104
105         for (argc = 0; argv[argc]; argc++)
106                 ; /* just counting */
107         nargv = malloc(sizeof(*nargv) * (argc + 2));
108
109         nargv[0] = "perf";
110         for (argc = 0; argv[argc]; argc++)
111                 nargv[argc + 1] = argv[argc];
112         nargv[argc + 1] = NULL;
113         return nargv;
114 }
115
116 int execv_perf_cmd(const char **argv) {
117         const char **nargv = prepare_perf_cmd(argv);
118
119         /* execvp() can only ever return if it fails */
120         execvp("perf", (char **)nargv);
121
122         free(nargv);
123         return -1;
124 }
125
126
127 int execl_perf_cmd(const char *cmd,...)
128 {
129         int argc;
130         const char *argv[MAX_ARGS + 1];
131         const char *arg;
132         va_list param;
133
134         va_start(param, cmd);
135         argv[0] = cmd;
136         argc = 1;
137         while (argc < MAX_ARGS) {
138                 arg = argv[argc++] = va_arg(param, char *);
139                 if (!arg)
140                         break;
141         }
142         va_end(param);
143         if (MAX_ARGS <= argc)
144                 return error("too many args to run %s", cmd);
145
146         argv[argc] = NULL;
147         return execv_perf_cmd(argv);
148 }