exec_cmd.c 3.2 KB

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