blob: 2745605dba11f4d334c15a294326aa0c7ac2bfc9 [file] [log] [blame]
Ingo Molnar07800602009-04-20 15:00:56 +02001#include "cache.h"
2#include "exec_cmd.h"
3#include "quote.h"
Ingo Molnarf37a2912009-07-01 12:37:06 +02004
5#include <string.h>
6
Ingo Molnar07800602009-04-20 15:00:56 +02007#define MAX_ARGS 32
8
Ingo Molnar07800602009-04-20 15:00:56 +02009static const char *argv_exec_path;
10static const char *argv0_path;
11
12const 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
44const 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) {
Ingo Molnarf37a2912009-07-01 12:37:06 +020056 argv0_path = xstrndup(argv0, slash - argv0);
Ingo Molnar07800602009-04-20 15:00:56 +020057 return slash + 1;
58 }
59
60 return argv0;
61}
62
63void 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. */
74const 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
89static 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
101void 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
119const 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
135int 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
146int 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}