Browse Source

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
René Scharfe 8 years ago committed by Junio C Hamano
parent
commit
e0ca1ca20a
  1. 91
      compat/mingw.c

91
compat/mingw.c

@ -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);

path = mingw_getenv("PATH");
if (!path)
return NULL;


while (!prog && *path) while (!prog) {
prog = lookup_prog(*path++, cmd, isexe, exe_only); 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…
Cancel
Save