From: "René Scharfe" <l.s.r@web.de>
To: Git List <git@vger.kernel.org>
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Johannes Sixt <j6t@kdbg.org>, Junio C Hamano <gitster@pobox.com>
Subject: [PATCH] mingw: simplify PATH handling
Date: Sat, 20 May 2017 17:29:18 +0200 [thread overview]
Message-ID: <c5b7292f-6367-e4a9-2ee0-96b93b1b587f@web.de> (raw)
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.
Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
compat/mingw.c | 96 ++++++++++++++--------------------------------------------
1 file changed, 22 insertions(+), 74 deletions(-)
diff --git a/compat/mingw.c b/compat/mingw.c
index 5113071bc7..7bc61d4066 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1154,67 +1154,15 @@ static const char *parse_interpreter(const char *cmd)
}
/*
- * 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) {
- free(envpath);
- 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
* (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];
wchar_t wpath[MAX_PATH];
- snprintf(path, sizeof(path), "%s\\%s.exe", dir, cmd);
+ snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
if (xutftowcs_path(wpath, path) < 0)
return NULL;
@@ -1235,17 +1183,27 @@ 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.
* 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;
int len = strlen(cmd);
int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
if (strchr(cmd, '/') || strchr(cmd, '\\'))
- prog = xstrdup(cmd);
+ return xstrdup(cmd);
- while (!prog && *path)
- prog = lookup_prog(*path++, cmd, isexe, exe_only);
+ path = mingw_getenv("PATH");
+ if (!path)
+ return NULL;
+
+ for (; !prog && *path; path++) {
+ const char *sep = strchrnul(path, ';');
+ if (sep == path)
+ continue;
+ prog = lookup_prog(path, sep - path, cmd, isexe, exe_only);
+ path = sep;
+ }
return prog;
}
@@ -1569,13 +1527,10 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
}
if (getenv("GIT_STRACE_COMMANDS")) {
- char **path = get_path_split();
- char *p = path_lookup("strace.exe", path, 1);
+ char *p = path_lookup("strace.exe", 1);
if (!p) {
- free_path_split(path);
return error("strace not found!");
}
- free_path_split(path);
if (xutftowcs_path(wcmd, p) < 0) {
free(p);
return -1;
@@ -1634,8 +1589,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
int fhin, int fhout, int fherr)
{
pid_t pid;
- char **path = get_path_split();
- char *prog = path_lookup(cmd, path, 0);
+ char *prog = path_lookup(cmd, 0);
if (!prog) {
errno = ENOENT;
@@ -1646,7 +1600,7 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
if (interpr) {
const char *argv0 = argv[0];
- char *iprog = path_lookup(interpr, path, 1);
+ char *iprog = path_lookup(interpr, 1);
argv[0] = prog;
if (!iprog) {
errno = ENOENT;
@@ -1664,21 +1618,18 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
fhin, fhout, fherr);
free(prog);
}
- free_path_split(path);
return pid;
}
static int try_shell_exec(const char *cmd, char *const *argv)
{
const char *interpr = parse_interpreter(cmd);
- char **path;
char *prog;
int pid = 0;
if (!interpr)
return 0;
- path = get_path_split();
- prog = path_lookup(interpr, path, 1);
+ prog = path_lookup(interpr, 1);
if (prog) {
int argc = 0;
#ifndef _MSC_VER
@@ -1700,7 +1651,6 @@ static int try_shell_exec(const char *cmd, char *const *argv)
free(prog);
free(argv2);
}
- free_path_split(path);
return pid;
}
@@ -1722,8 +1672,7 @@ int mingw_execv(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, path, 0);
+ char *prog = path_lookup(cmd, 0);
if (prog) {
mingw_execv(prog, argv);
@@ -1731,7 +1680,6 @@ int mingw_execvp(const char *cmd, char *const *argv)
} else
errno = ENOENT;
- free_path_split(path);
return -1;
}
--
2.12.1.windows.1
next reply other threads:[~2017-05-20 15:29 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-20 15:29 René Scharfe [this message]
2017-05-20 17:00 ` [PATCH] mingw: simplify PATH handling Johannes Sixt
2017-05-20 19:35 ` René Scharfe
2017-05-20 19:35 ` [PATCH v2] " René Scharfe
2017-05-22 12:58 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c5b7292f-6367-e4a9-2ee0-96b93b1b587f@web.de \
--to=l.s.r@web.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=j6t@kdbg.org \
--cc=johannes.schindelin@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).