linux/tools/perf/util/exec_cmd.c
<<
>>
Prefs
   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 = strndup(argv0, slash - argv0);
  57                return argv0_path ? slash + 1 : NULL;
  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
 119static const 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