mingw: simplify PATH handling
On Windows the environment variable PATH contains a semicolon-separated list of directories to search for, in order, when looking for the location of a binary to run. get_path_split() parses it and returns an array of string copies, which is iterated by path_lookup(), which in turn passes each entry to lookup_prog(). Change lookup_prog() to take the directory name as a length-limited string instead of as a NUL-terminated one and parse PATH directly in path_lookup(). This avoids memory allocations, simplifying the code. Helped-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Rene Scharfe <l.s.r@web.de> Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
10c78a162f
commit
e0ca1ca20a
|
@ -940,65 +940,15 @@ static const char *parse_interpreter(const char *cmd)
|
||||||
return p+1;
|
return p+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Splits the PATH into parts.
|
|
||||||
*/
|
|
||||||
static char **get_path_split(void)
|
|
||||||
{
|
|
||||||
char *p, **path, *envpath = mingw_getenv("PATH");
|
|
||||||
int i, n = 0;
|
|
||||||
|
|
||||||
if (!envpath || !*envpath)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
envpath = xstrdup(envpath);
|
|
||||||
p = envpath;
|
|
||||||
while (p) {
|
|
||||||
char *dir = p;
|
|
||||||
p = strchr(p, ';');
|
|
||||||
if (p) *p++ = '\0';
|
|
||||||
if (*dir) { /* not earlier, catches series of ; */
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!n)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ALLOC_ARRAY(path, n + 1);
|
|
||||||
p = envpath;
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
if (*p)
|
|
||||||
path[i++] = xstrdup(p);
|
|
||||||
p = p+strlen(p)+1;
|
|
||||||
} while (i < n);
|
|
||||||
path[i] = NULL;
|
|
||||||
|
|
||||||
free(envpath);
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_path_split(char **path)
|
|
||||||
{
|
|
||||||
char **p = path;
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (*p)
|
|
||||||
free(*p++);
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exe_only means that we only want to detect .exe files, but not scripts
|
* exe_only means that we only want to detect .exe files, but not scripts
|
||||||
* (which do not have an extension)
|
* (which do not have an extension)
|
||||||
*/
|
*/
|
||||||
static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_only)
|
static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
|
||||||
|
int isexe, int exe_only)
|
||||||
{
|
{
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
snprintf(path, sizeof(path), "%s/%s.exe", dir, cmd);
|
snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
|
||||||
|
|
||||||
if (!isexe && access(path, F_OK) == 0)
|
if (!isexe && access(path, F_OK) == 0)
|
||||||
return xstrdup(path);
|
return xstrdup(path);
|
||||||
|
@ -1013,17 +963,29 @@ static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_on
|
||||||
* Determines the absolute path of cmd using the split path in path.
|
* Determines the absolute path of cmd using the split path in path.
|
||||||
* If cmd contains a slash or backslash, no lookup is performed.
|
* If cmd contains a slash or backslash, no lookup is performed.
|
||||||
*/
|
*/
|
||||||
static char *path_lookup(const char *cmd, char **path, int exe_only)
|
static char *path_lookup(const char *cmd, int exe_only)
|
||||||
{
|
{
|
||||||
|
const char *path;
|
||||||
char *prog = NULL;
|
char *prog = NULL;
|
||||||
int len = strlen(cmd);
|
int len = strlen(cmd);
|
||||||
int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
|
int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
|
||||||
|
|
||||||
if (strchr(cmd, '/') || strchr(cmd, '\\'))
|
if (strchr(cmd, '/') || strchr(cmd, '\\'))
|
||||||
prog = xstrdup(cmd);
|
return xstrdup(cmd);
|
||||||
|
|
||||||
while (!prog && *path)
|
path = mingw_getenv("PATH");
|
||||||
prog = lookup_prog(*path++, cmd, isexe, exe_only);
|
if (!path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (!prog) {
|
||||||
|
const char *sep = strchrnul(path, ';');
|
||||||
|
int dirlen = sep - path;
|
||||||
|
if (dirlen)
|
||||||
|
prog = lookup_prog(path, dirlen, cmd, isexe, exe_only);
|
||||||
|
if (!*sep)
|
||||||
|
break;
|
||||||
|
path = sep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
return prog;
|
return prog;
|
||||||
}
|
}
|
||||||
|
@ -1190,8 +1152,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
|
||||||
int fhin, int fhout, int fherr)
|
int fhin, int fhout, int fherr)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char **path = get_path_split();
|
char *prog = path_lookup(cmd, 0);
|
||||||
char *prog = path_lookup(cmd, path, 0);
|
|
||||||
|
|
||||||
if (!prog) {
|
if (!prog) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
@ -1202,7 +1163,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
|
||||||
|
|
||||||
if (interpr) {
|
if (interpr) {
|
||||||
const char *argv0 = argv[0];
|
const char *argv0 = argv[0];
|
||||||
char *iprog = path_lookup(interpr, path, 1);
|
char *iprog = path_lookup(interpr, 1);
|
||||||
argv[0] = prog;
|
argv[0] = prog;
|
||||||
if (!iprog) {
|
if (!iprog) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
@ -1220,21 +1181,18 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
|
||||||
fhin, fhout, fherr);
|
fhin, fhout, fherr);
|
||||||
free(prog);
|
free(prog);
|
||||||
}
|
}
|
||||||
free_path_split(path);
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int try_shell_exec(const char *cmd, char *const *argv)
|
static int try_shell_exec(const char *cmd, char *const *argv)
|
||||||
{
|
{
|
||||||
const char *interpr = parse_interpreter(cmd);
|
const char *interpr = parse_interpreter(cmd);
|
||||||
char **path;
|
|
||||||
char *prog;
|
char *prog;
|
||||||
int pid = 0;
|
int pid = 0;
|
||||||
|
|
||||||
if (!interpr)
|
if (!interpr)
|
||||||
return 0;
|
return 0;
|
||||||
path = get_path_split();
|
prog = path_lookup(interpr, 1);
|
||||||
prog = path_lookup(interpr, path, 1);
|
|
||||||
if (prog) {
|
if (prog) {
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
const char **argv2;
|
const char **argv2;
|
||||||
|
@ -1253,7 +1211,6 @@ static int try_shell_exec(const char *cmd, char *const *argv)
|
||||||
free(prog);
|
free(prog);
|
||||||
free(argv2);
|
free(argv2);
|
||||||
}
|
}
|
||||||
free_path_split(path);
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,8 +1232,7 @@ int mingw_execv(const char *cmd, char *const *argv)
|
||||||
|
|
||||||
int mingw_execvp(const char *cmd, char *const *argv)
|
int mingw_execvp(const char *cmd, char *const *argv)
|
||||||
{
|
{
|
||||||
char **path = get_path_split();
|
char *prog = path_lookup(cmd, 0);
|
||||||
char *prog = path_lookup(cmd, path, 0);
|
|
||||||
|
|
||||||
if (prog) {
|
if (prog) {
|
||||||
mingw_execv(prog, argv);
|
mingw_execv(prog, argv);
|
||||||
|
@ -1284,7 +1240,6 @@ int mingw_execvp(const char *cmd, char *const *argv)
|
||||||
} else
|
} else
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
|
||||||
free_path_split(path);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue