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 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 25const 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 44void 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. */ 55const 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 70static 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 82void 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 100static 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 116int 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 127int 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