From 23960ed3c315dc0f39cebcf317ff4d3ba16ccee8 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 12 Jan 2007 10:10:25 +0100 Subject: [PATCH] Enable the spawn workhorse function to spawn shell scripts. For this purpose the path lookup is done manually, and the found file is inspected for the interpreter. If one is found, the script is spawned under the interpreter; otherwise, the program is spawned normally. --- spawn-pipe.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/spawn-pipe.c b/spawn-pipe.c index 87ad789775..53a1487d32 100644 --- a/spawn-pipe.c +++ b/spawn-pipe.c @@ -3,6 +3,53 @@ extern char **environ; +#ifdef __MINGW32__ +static char *lookup_prog(const char *dir, const char *cmd, int tryexe) +{ + char path[MAX_PATH]; + snprintf(path, sizeof(path), "%s/%s.exe", dir, cmd); + + if (tryexe && access(path, 0) == 0) + return xstrdup(path); + path[strlen(path)-4] = '\0'; + if (access(path, 0) == 0) + return xstrdup(path); + return NULL; +} + +/* + * Determines the absolute path of cmd based on the PATH environment variable. + * If cmd contains a slash or backslash, no lookup is performed. + */ +static char *path_lookup(const char *cmd) +{ + char *p, *envpath = getenv("PATH"); + char *prog = NULL; + int len = strlen(cmd); + int tryexe = len < 4 || strcasecmp(cmd+len-4, ".exe"); + + if (strchr(cmd, '/') || strchr(cmd, '\\') || + !envpath || !*envpath) + envpath = ""; + envpath = xstrdup(envpath); + p = envpath; + while (p && !prog) { + const char *dir = p; + p = strchr(p, ';'); + if (p) *p++ = '\0'; + if (*dir) + prog = lookup_prog(dir, cmd, tryexe); + } + free(envpath); + if (!prog) { + prog = lookup_prog(".", cmd, tryexe); + if (!prog) + prog = xstrdup(cmd); + } + return prog; +} +#endif + /* cmd specifies the command to invoke. * argv specifies its arguments; argv[0] will be replaced by the basename of cmd. * env specifies the environment. @@ -21,7 +68,8 @@ int spawnvpe_pipe(const char *cmd, const char **argv, const char **env, #ifdef __MINGW32__ int s0 = -1, s1 = -1, argc; - const char **qargv; + char *prog; + const char **qargv, *interpr; if (!cmd_basename) cmd_basename = strrchr(cmd, '\\'); @@ -79,15 +127,26 @@ int spawnvpe_pipe(const char *cmd, const char **argv, const char **env, } } + prog = path_lookup(cmd); + interpr = parse_interpreter(prog); + for (argc = 0; argv[argc];) argc++; qargv = xmalloc((argc+2)*sizeof(char*)); - quote_argv(qargv, argv); + if (!interpr) { + quote_argv(qargv, argv); + pid = spawnve(_P_NOWAIT, prog, qargv, env); + } else { + qargv[0] = interpr; + argv[0] = prog; + quote_argv(&qargv[1], argv); + pid = spawnvpe(_P_NOWAIT, interpr, qargv, env); + } - pid = spawnvpe(_P_NOWAIT, cmd, qargv, env); if (pid < 0) die("unable to run %s", cmd); free(qargv); /* TODO: quoted args should be freed, too */ + free(prog); if (s0 >= 0) { dup2(s0, 0);