Root/tools/perf/util/exec_cmd.c

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
9static 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) {
56        argv0_path = xstrndup(argv0, slash - argv0);
57        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}
168

Archive Download this file



interactive