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