]>
Commit | Line | Data |
---|---|---|
07800601 IM |
1 | #include "cache.h" |
2 | #include "exec_cmd.h" | |
3 | #include "quote.h" | |
f37a291c IM |
4 | |
5 | #include <string.h> | |
6 | ||
07800601 IM |
7 | #define MAX_ARGS 32 |
8 | ||
07800601 IM |
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) { | |
f37a291c | 56 | argv0_path = xstrndup(argv0, slash - argv0); |
07800601 IM |
57 | return slash + 1; |
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 | 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 | } |