--- setuptools-5.4.1/launcher.c.orig 2014-06-29 02:40:09.000000000 +0100 +++ setuptools-5.4.1/launcher.c 2014-10-19 13:37:21.272787900 +0100 @@ -104,9 +104,19 @@ } -char *find_exe(char *exename, char *script) { +int file_exists(char* path) +{ + DWORD attrib = GetFileAttributes(path); + + if ((attrib == INVALID_FILE_ATTRIBUTES) || (attrib & FILE_ATTRIBUTE_DIRECTORY)) return 0; + return 1; +} + +char *find_exe(char *exename, char *script, int search_in_path) { char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; char path[_MAX_PATH], c, *result; + char *path_env, *path_env_start; + int maximum, needs_exe = 0; /* convert slashes to backslashes for uniform search below */ result = exename; @@ -116,6 +126,34 @@ if (drive[0] || dir[0]=='\\') { return loadable_exe(exename); /* absolute path, use directly */ } + + if (search_in_path) { + if (strstr(exename, ".exe") == NULL) needs_exe = 1; + char *path_env = getenv("PATH"); + while (path_env != NULL) { + path_env_start = path_env; + path_env = strchr(path_env, ';'); + maximum = _MAX_PATH - 2 - strlen(exename) - (needs_exe * strlen(".exe")); + if (path_env == NULL) { + strncpy(path, path_env_start, maximum); + } + else { + maximum = path_env - path_env_start < maximum ? path_env - path_env_start : maximum; + memcpy(path, path_env_start, maximum); + ++path_env; + } + path[maximum] = '\0'; + strcat(path, "\\"); + strcat(path, exename); + if (needs_exe) strcat(path, ".exe"); + /* printf("Checking %s\n", path); */ + if (file_exists(path)) { + /* printf("Found\n"); */ + return loadable_exe(path); + } + } + } + /* Use the script's parent directory, which should be the Python home (This should only be used for bdist_wininst-installed scripts, because easy_install-ed scripts use the absolute path to python[w].exe @@ -206,7 +244,7 @@ // set-up control handler callback funciotn SetConsoleCtrlHandler((PHANDLER_ROUTINE) control_handler, TRUE); if (!CreateProcessA(NULL, commandline, NULL, NULL, TRUE, 0, NULL, NULL, &s_info, &p_info)) { - fprintf(stderr, "failed to create process.\n"); + fprintf(stderr, "failed to create process (%s).\n", commandline); return 0; } child_pid = p_info.dwProcessId; @@ -256,6 +294,9 @@ char *ptr, *end; /* working pointers for string manipulation */ char *cmdline; int i, parsedargc; /* loop counter */ + char *env, *first_space; + int skip = 2; + int search_in_path = 0; /* compute script name from our .exe name*/ GetModuleFileNameA(NULL, script, sizeof(script)); @@ -284,12 +325,24 @@ strcpy(python, "#!python.exe"); } - parsedargs = parse_argv(python+2, &parsedargc); + /* Check if "env" appears before the first space and skip + ahead to the next space. */ + env = strstr(python+skip, "env"); + first_space = strchr(python+skip, ' '); + if (env != NULL && (first_space == NULL || env < first_space)) { + search_in_path = 1; + env += 3; + while (*env && *env != ' ') + ++env; + skip = env - python; + } + + parsedargs = parse_argv(python+skip, &parsedargc); /* Using spawnv() can fail strangely if you e.g. find the Cygwin Python, so we'll make sure Windows can find and load it */ - ptr = find_exe(parsedargs[0], script); + ptr = find_exe(parsedargs[0], script, search_in_path); if (!ptr) { return fail("Cannot find Python executable %s\n", parsedargs[0]); }