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