Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux...
[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 #ifdef RUNTIME_PREFIX
15         static const char *prefix;
16 #else
17         static const char *prefix = PREFIX;
18 #endif
19         struct strbuf d = STRBUF_INIT;
20
21         if (is_absolute_path(path))
22                 return path;
23
24 #ifdef RUNTIME_PREFIX
25         assert(argv0_path);
26         assert(is_absolute_path(argv0_path));
27
28         if (!prefix &&
29             !(prefix = strip_path_suffix(argv0_path, PERF_EXEC_PATH)) &&
30             !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
31             !(prefix = strip_path_suffix(argv0_path, "perf"))) {
32                 prefix = PREFIX;
33                 fprintf(stderr, "RUNTIME_PREFIX requested, "
34                                 "but prefix computation failed.  "
35                                 "Using static fallback '%s'.\n", prefix);
36         }
37 #endif
38
39         strbuf_addf(&d, "%s/%s", prefix, path);
40         path = strbuf_detach(&d, NULL);
41         return path;
42 }
43
44 const char *perf_extract_argv0_path(const char *argv0)
45 {
46         const char *slash;
47
48         if (!argv0 || !*argv0)
49                 return NULL;
50         slash = argv0 + strlen(argv0);
51
52         while (argv0 <= slash && !is_dir_sep(*slash))
53                 slash--;
54
55         if (slash >= argv0) {
56                 argv0_path = strndup(argv0, slash - argv0);
57                 return argv0_path ? slash + 1 : NULL;
58         }
59
60         return argv0;
61 }
62
63 void perf_set_argv_exec_path(const char *exec_path)
64 {
65         argv_exec_path = exec_path;
66         /*
67          * Propagate this setting to external programs.
68          */
69         setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
70 }
71
72
73 /* Returns the highest-priority, location to look for perf programs. */
74 const char *perf_exec_path(void)
75 {
76         const char *env;
77
78         if (argv_exec_path)
79                 return argv_exec_path;
80
81         env = getenv(EXEC_PATH_ENVIRONMENT);
82         if (env && *env) {
83                 return env;
84         }
85
86         return system_path(PERF_EXEC_PATH);
87 }
88
89 static void add_path(struct strbuf *out, const char *path)
90 {
91         if (path && *path) {
92                 if (is_absolute_path(path))
93                         strbuf_addstr(out, path);
94                 else
95                         strbuf_addstr(out, make_nonrelative_path(path));
96
97                 strbuf_addch(out, PATH_SEP);
98         }
99 }
100
101 void setup_path(void)
102 {
103         const char *old_path = getenv("PATH");
104         struct strbuf new_path = STRBUF_INIT;
105
106         add_path(&new_path, perf_exec_path());
107         add_path(&new_path, argv0_path);
108
109         if (old_path)
110                 strbuf_addstr(&new_path, old_path);
111         else
112                 strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
113
114         setenv("PATH", new_path.buf, 1);
115
116         strbuf_release(&new_path);
117 }
118
119 static const char **prepare_perf_cmd(const char **argv)
120 {
121         int argc;
122         const char **nargv;
123
124         for (argc = 0; argv[argc]; argc++)
125                 ; /* just counting */
126         nargv = malloc(sizeof(*nargv) * (argc + 2));
127
128         nargv[0] = "perf";
129         for (argc = 0; argv[argc]; argc++)
130                 nargv[argc + 1] = argv[argc];
131         nargv[argc + 1] = NULL;
132         return nargv;
133 }
134
135 int execv_perf_cmd(const char **argv) {
136         const char **nargv = prepare_perf_cmd(argv);
137
138         /* execvp() can only ever return if it fails */
139         execvp("perf", (char **)nargv);
140
141         free(nargv);
142         return -1;
143 }
144
145
146 int execl_perf_cmd(const char *cmd,...)
147 {
148         int argc;
149         const char *argv[MAX_ARGS + 1];
150         const char *arg;
151         va_list param;
152
153         va_start(param, cmd);
154         argv[0] = cmd;
155         argc = 1;
156         while (argc < MAX_ARGS) {
157                 arg = argv[argc++] = va_arg(param, char *);
158                 if (!arg)
159                         break;
160         }
161         va_end(param);
162         if (MAX_ARGS <= argc)
163                 return error("too many args to run %s", cmd);
164
165         argv[argc] = NULL;
166         return execv_perf_cmd(argv);
167 }