exec_cmd.c 2.7 KB

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