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