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