#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
#include "path.h"
#include "run-command.h"
#include "strvec.h"
#include "trace.h"
#include "trace2.h"
#if defined(RUNTIME_PREFIX)
#if defined(HAVE_NS_GET_EXECUTABLE_PATH)
#include <mach-o/dyld.h>
#endif
#if defined(HAVE_BSD_KERN_PROC_SYSCTL)
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#endif
#define MAX_ARGS …
static const char *system_prefix(void);
#ifdef RUNTIME_PREFIX
static const char *executable_dirname;
static const char *system_prefix(void)
{
static const char *prefix;
assert(executable_dirname);
assert(is_absolute_path(executable_dirname));
if (!prefix &&
!(prefix = strip_path_suffix(executable_dirname, GIT_EXEC_PATH)) &&
!(prefix = strip_path_suffix(executable_dirname, BINDIR)) &&
!(prefix = strip_path_suffix(executable_dirname, "git"))) {
prefix = FALLBACK_RUNTIME_PREFIX;
trace_printf("RUNTIME_PREFIX requested, "
"but prefix computation failed. "
"Using static fallback '%s'.\n", prefix);
}
return prefix;
}
static int git_get_exec_path_from_argv0(struct strbuf *buf, const char *argv0)
{
const char *slash;
if (!argv0 || !*argv0)
return -1;
slash = find_last_dir_sep(argv0);
if (slash) {
trace_printf("trace: resolved executable path from argv0: %s\n",
argv0);
strbuf_add_absolute_path(buf, argv0);
return 0;
}
return -1;
}
#ifdef PROCFS_EXECUTABLE_PATH
static int git_get_exec_path_procfs(struct strbuf *buf)
{
if (strbuf_realpath(buf, PROCFS_EXECUTABLE_PATH, 0)) {
trace_printf(
"trace: resolved executable path from procfs: %s\n",
buf->buf);
return 0;
}
return -1;
}
#endif
#ifdef HAVE_BSD_KERN_PROC_SYSCTL
static int git_get_exec_path_bsd_sysctl(struct strbuf *buf)
{
int mib[4];
char path[MAXPATHLEN];
size_t cb = sizeof(path);
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
if (!sysctl(mib, 4, path, &cb, NULL, 0)) {
trace_printf(
"trace: resolved executable path from sysctl: %s\n",
path);
strbuf_addstr(buf, path);
return 0;
}
return -1;
}
#endif
#ifdef HAVE_NS_GET_EXECUTABLE_PATH
static int git_get_exec_path_darwin(struct strbuf *buf)
{
char path[PATH_MAX];
uint32_t size = sizeof(path);
if (!_NSGetExecutablePath(path, &size)) {
trace_printf(
"trace: resolved executable path from Darwin stack: %s\n",
path);
strbuf_addstr(buf, path);
return 0;
}
return -1;
}
#endif
#ifdef HAVE_ZOS_GET_EXECUTABLE_PATH
static int git_get_exec_path_zos(struct strbuf *buf)
{
char *dir = __getprogramdir();
char *exe = getprogname();
if (dir && exe) {
strbuf_addf(buf, "%s/%s", dir, exe);
return 0;
}
return -1;
}
#endif
#ifdef HAVE_WPGMPTR
static int git_get_exec_path_wpgmptr(struct strbuf *buf)
{
int len = wcslen(_wpgmptr) * 3 + 1;
strbuf_grow(buf, len);
len = xwcstoutf(buf->buf, _wpgmptr, len);
if (len < 0)
return -1;
buf->len += len;
return 0;
}
#endif
static int git_get_exec_path(struct strbuf *buf, const char *argv0)
{
if (
#ifdef HAVE_BSD_KERN_PROC_SYSCTL
git_get_exec_path_bsd_sysctl(buf) &&
#endif
#ifdef HAVE_NS_GET_EXECUTABLE_PATH
git_get_exec_path_darwin(buf) &&
#endif
#ifdef PROCFS_EXECUTABLE_PATH
git_get_exec_path_procfs(buf) &&
#endif
#ifdef HAVE_WPGMPTR
git_get_exec_path_wpgmptr(buf) &&
#endif
#ifdef HAVE_ZOS_GET_EXECUTABLE_PATH
git_get_exec_path_zos(buf) &&
#endif
git_get_exec_path_from_argv0(buf, argv0)) {
return -1;
}
if (strbuf_normalize_path(buf)) {
trace_printf("trace: could not normalize path: %s\n", buf->buf);
return -1;
}
trace2_cmd_path(buf->buf);
return 0;
}
void git_resolve_executable_dir(const char *argv0)
{
struct strbuf buf = STRBUF_INIT;
char *resolved;
const char *slash;
if (git_get_exec_path(&buf, argv0)) {
trace_printf(
"trace: could not determine executable path from: %s\n",
argv0);
strbuf_release(&buf);
return;
}
resolved = strbuf_detach(&buf, NULL);
slash = find_last_dir_sep(resolved);
if (slash)
resolved[slash - resolved] = '\0';
executable_dirname = resolved;
trace_printf("trace: resolved executable dir: %s\n",
executable_dirname);
}
#else
static const char *system_prefix(void)
{ … }
void git_resolve_executable_dir(const char *argv0 UNUSED)
{ … }
#endif
char *system_path(const char *path)
{ … }
static const char *exec_path_value;
void git_set_exec_path(const char *exec_path)
{ … }
const char *git_exec_path(void)
{ … }
static void add_path(struct strbuf *out, const char *path)
{ … }
void setup_path(void)
{ … }
const char **prepare_git_cmd(struct strvec *out, const char **argv)
{ … }
int execv_git_cmd(const char **argv)
{ … }
int execl_git_cmd(const char *cmd, ...)
{ … }