exec_cmd.c 3.03 KB
Newer Older
1 2
#include "cache.h"
#include "exec_cmd.h"
3
#include "quote.h"
4
#include "argv-array.h"
5 6
#define MAX_ARGS	32

7
static const char *argv_exec_path;
8
static const char *argv0_path;
9

10
char *system_path(const char *path)
11
{
12 13 14
#ifdef RUNTIME_PREFIX
	static const char *prefix;
#else
15
	static const char *prefix = PREFIX;
16
#endif
17 18 19
	struct strbuf d = STRBUF_INIT;

	if (is_absolute_path(path))
20
		return xstrdup(path);
21

22 23 24 25
#ifdef RUNTIME_PREFIX
	assert(argv0_path);
	assert(is_absolute_path(argv0_path));

26 27 28 29
	if (!prefix &&
	    !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) &&
	    !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
	    !(prefix = strip_path_suffix(argv0_path, "git"))) {
30
		prefix = PREFIX;
31
		trace_printf("RUNTIME_PREFIX requested, "
32 33 34 35 36
				"but prefix computation failed.  "
				"Using static fallback '%s'.\n", prefix);
	}
#endif

37
	strbuf_addf(&d, "%s/%s", prefix, path);
38
	return strbuf_detach(&d, NULL);
39 40
}

41
void git_extract_argv0_path(const char *argv0)
42
{
43 44 45
	const char *slash;

	if (!argv0 || !*argv0)
46
		return;
47

48
	slash = find_last_dir_sep(argv0);
49

50
	if (slash)
51
		argv0_path = xstrndup(argv0, slash - argv0);
52 53
}

54
void git_set_argv_exec_path(const char *exec_path)
55
{
56
	argv_exec_path = exec_path;
57 58 59 60
	/*
	 * Propagate this setting to external programs.
	 */
	setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
61 62 63 64
}


/* Returns the highest-priority, location to look for git programs. */
65
const char *git_exec_path(void)
66
{
67
	static char *cached_exec_path;
68

69 70
	if (argv_exec_path)
		return argv_exec_path;
71

72 73 74 75 76 77
	if (!cached_exec_path) {
		const char *env = getenv(EXEC_PATH_ENVIRONMENT);
		if (env && *env)
			cached_exec_path = xstrdup(env);
		else
			cached_exec_path = system_path(GIT_EXEC_PATH);
78
	}
79
	return cached_exec_path;
80 81
}

82 83 84
static void add_path(struct strbuf *out, const char *path)
{
	if (path && *path) {
85
		strbuf_add_absolute_path(out, path);
86
		strbuf_addch(out, PATH_SEP);
87 88 89
	}
}

90
void setup_path(void)
91 92
{
	const char *old_path = getenv("PATH");
93
	struct strbuf new_path = STRBUF_INIT;
94

95
	add_path(&new_path, git_exec_path());
96 97 98 99

	if (old_path)
		strbuf_addstr(&new_path, old_path);
	else
100
		strbuf_addstr(&new_path, _PATH_DEFPATH);
101 102 103 104 105

	setenv("PATH", new_path.buf, 1);

	strbuf_release(&new_path);
}
106

107
const char **prepare_git_cmd(struct argv_array *out, const char **argv)
108
{
109 110 111
	argv_array_push(out, "git");
	argv_array_pushv(out, argv);
	return out->argv;
112 113 114
}

int execv_git_cmd(const char **argv) {
115 116 117 118
	struct argv_array nargv = ARGV_ARRAY_INIT;

	prepare_git_cmd(&nargv, argv);
	trace_argv_printf(nargv.argv, "trace: exec:");
119

120
	/* execvp() can only ever return if it fails */
121
	sane_execvp("git", (char **)nargv.argv);
122

123
	trace_printf("trace: exec failed: %s\n", strerror(errno));
124

125
	argv_array_clear(&nargv);
126
	return -1;
127 128 129
}


Junio C Hamano's avatar
Junio C Hamano committed
130
int execl_git_cmd(const char *cmd,...)
131 132
{
	int argc;
Junio C Hamano's avatar
Junio C Hamano committed
133 134
	const char *argv[MAX_ARGS + 1];
	const char *arg;
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
	va_list param;

	va_start(param, cmd);
	argv[0] = cmd;
	argc = 1;
	while (argc < MAX_ARGS) {
		arg = argv[argc++] = va_arg(param, char *);
		if (!arg)
			break;
	}
	va_end(param);
	if (MAX_ARGS <= argc)
		return error("too many args to run %s", cmd);

	argv[argc] = NULL;
	return execv_git_cmd(argv);
}