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