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