Permalink
Browse files

Windows: when searching path, look only for .com and .exe files

  • Loading branch information...
1 parent 422c139 commit 8ed2ffb2bf35304675d06cd07c3f440dccd46eb2 @piscisaureus piscisaureus committed Aug 18, 2011
Showing with 45 additions and 70 deletions.
  1. +45 −70 src/win/process.c
View
@@ -51,9 +51,6 @@ typedef struct env_var {
}
-static const wchar_t DEFAULT_PATH_EXT[10] = L".COM;.EXE";
-
-
static void uv_process_init(uv_process_t* handle) {
handle->type = UV_PROCESS;
handle->flags = 0;
@@ -153,10 +150,14 @@ static wchar_t* search_path_join_test(const wchar_t* dir,
wcsncpy(result_pos, name, name_len);
result_pos += name_len;
- /* Copy extension */
if (ext_len) {
- result_pos[0] = L'.';
- result_pos++;
+ /* Add a dot if the filename didn't end with one */
+ if (name_len && result_pos[-1] != '.') {
+ result_pos[0] = L'.';
+ result_pos++;
+ }
+
+ /* Copy extension */
wcsncpy(result_pos, ext, ext_len);
result_pos += ext_len;
}
@@ -185,54 +186,39 @@ static wchar_t* path_search_walk_ext(const wchar_t *dir,
int name_len,
wchar_t *cwd,
int cwd_len,
- const wchar_t *path_ext,
int name_has_ext) {
- wchar_t* result = NULL;
-
- const wchar_t *ext_start,
- *ext_end = path_ext;
+ wchar_t* result;
- /* If the name itself has a nonemtpy extension, try this extension first */
+ /* If the name itself has a nonempty extension, try this extension first */
if (name_has_ext) {
result = search_path_join_test(dir, dir_len,
name, name_len,
L"", 0,
cwd, cwd_len);
- }
-
- /* Add path_ext extensions and try to find a name that matches */
- while (result == NULL) {
- if (*ext_end == L'\0') {
- break;
- }
-
- /* Skip the separator that ext_end now points to */
- if (ext_end != path_ext) {
- ext_end++;
+ if (result != NULL) {
+ return result;
}
+ }
- /* Find the next dot in path_ext */
- ext_start = wcschr(ext_end, L'.');
- if (ext_start == NULL) {
- break;
- }
-
- /* Skip the dot */
- ext_start++;
-
- /* Slice until we found a ; or alternatively a \0 */
- ext_end = wcschr(ext_start, L';');
- if (ext_end == NULL) {
- ext_end = wcschr(ext_start, '\0');
- }
+ /* Try .com extension */
+ result = search_path_join_test(dir, dir_len,
+ name, name_len,
+ L"com", 3,
+ cwd, cwd_len);
+ if (result != NULL) {
+ return result;
+ }
- result = search_path_join_test(dir, dir_len,
- name, name_len,
- ext_start, (ext_end - ext_start),
- cwd, cwd_len);
+ /* Try .exe extension */
+ result = search_path_join_test(dir, dir_len,
+ name, name_len,
+ L"exe", 3,
+ cwd, cwd_len);
+ if (result != NULL) {
+ return result;
}
- return result;
+ return NULL;
}
@@ -243,35 +229,28 @@ static wchar_t* path_search_walk_ext(const wchar_t *dir,
*
* It tries to return an absolute filename.
*
- * Furthermore, it tries to follow the semantics that cmd.exe uses as closely
- * as possible:
+ * Furthermore, it tries to follow the semantics that cmd.exe, with this
+ * exception that PATHEXT environment variable isn't used. Since CreateProcess
+ * can start only .com and .exe files, only those extensions are tried. This
+ * behavior equals that of msvcrt's spawn functions.
*
* - Do not search the path if the filename already contains a path (either
* relative or absolute).
- * (but do use path_ext)
*
* - If there's really only a filename, check the current directory for file,
* then search all path directories.
*
- * - If filename specifies has *any* extension, search for the file with the
+ * - If filename specified has *any* extension, search for the file with the
* specified extension first.
- * (not necessary an executable one or one that appears in path_ext;
- * *but* no extension or just a dot is *not* allowed)
*
* - If the literal filename is not found in a directory, try *appending*
- * (not replacing) extensions from path_ext in the specified order.
- * (an extension consisting of just a dot *may* appear in path_ext;
- * unlike what happens if the specified filename ends with a dot,
- * if path_ext specifies a single dot cmd.exe *does* look for an
- * extension-less file)
+ * (not replacing) .com first and then .exe.
*
* - The path variable may contain relative paths; relative paths are relative
* to the cwd.
*
* - Directories in path may or may not end with a trailing backslash.
*
- * - Extensions path_ext portions must always start with a dot.
- *
* - CMD does not trim leading/trailing whitespace from path/pathex entries
* nor from the environment variables as a whole.
*
@@ -281,13 +260,10 @@ static wchar_t* path_search_walk_ext(const wchar_t *dir,
* continue searching.
*
* TODO: correctly interpret UNC paths
- * TODO: check with cmd what should happen when a pathext entry does not start
- * with a dot
*/
static wchar_t* search_path(const wchar_t *file,
wchar_t *cwd,
- const wchar_t *path,
- const wchar_t *path_ext) {
+ const wchar_t *path) {
int file_has_dir;
wchar_t* result = NULL;
wchar_t *file_name_start;
@@ -320,12 +296,12 @@ static wchar_t* search_path(const wchar_t *file,
name_has_ext = (dot != NULL && dot[1] != L'\0');
if (file_has_dir) {
- /* The file has a path inside, don't use path (but do use path_ex) */
+ /* The file has a path inside, don't use path */
result = path_search_walk_ext(
file, file_name_start - file,
file_name_start, file_len - (file_name_start - file),
cwd, cwd_len,
- path_ext, name_has_ext);
+ name_has_ext);
} else {
const wchar_t *dir_start,
@@ -335,7 +311,7 @@ static wchar_t* search_path(const wchar_t *file,
result = path_search_walk_ext(L"", 0,
file, file_len,
cwd, cwd_len,
- path_ext, name_has_ext);
+ name_has_ext);
while (result == NULL) {
if (*dir_end == L'\0') {
@@ -364,7 +340,7 @@ static wchar_t* search_path(const wchar_t *file,
result = path_search_walk_ext(dir_start, dir_end - dir_start,
file, file_len,
cwd, cwd_len,
- path_ext, name_has_ext);
+ name_has_ext);
}
}
@@ -381,7 +357,7 @@ wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
i, quote_hit;
wchar_t* start;
- /*
+ /*
* Check if the string must be quoted;
* if unnecessary, don't do it, it may only confuse older programs.
*/
@@ -397,7 +373,7 @@ wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
}
if (NULL == wcspbrk(source, L"\"\\")) {
- /*
+ /*
* No embedded double quotes or backlashes, so I can just wrap
* quote marks around the whole thing.
*/
@@ -468,7 +444,7 @@ wchar_t* make_program_args(char** args, int verbatim_arguments) {
arg_count++;
}
- /* Adjust for potential quotes. Also assume the worst-case scenario
+ /* Adjust for potential quotes. Also assume the worst-case scenario
/* that every character needs escaping, so we need twice as much space. */
size = size * 2 + arg_count * 2;
@@ -511,7 +487,7 @@ wchar_t* make_program_args(char** args, int verbatim_arguments) {
* If we learn that people are passing in huge environment blocks
* then we should probably qsort() the array and then bsearch()
* to see if it contains this variable. But there are ownership
- * issues associated with that solution; this is the caller's
+ * issues associated with that solution; this is the caller's
* char**, and modifying it is rude.
*/
static void check_required_vars_contains_var(env_var_t* required, int size, const char* var) {
@@ -529,7 +505,7 @@ static void check_required_vars_contains_var(env_var_t* required, int size, cons
* The way windows takes environment variables is different than what C does;
* Windows wants a contiguous block of null-terminated strings, terminated
* with an additional null.
- *
+ *
* Windows has a few "essential" environment variables. winsock will fail
* to initialize if SYSTEMROOT is not defined; some APIs make reference to
* TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that
@@ -858,8 +834,7 @@ int uv_spawn(uv_process_t* process, uv_process_options_t options) {
application_path = search_path(application,
cwd,
- path,
- DEFAULT_PATH_EXT);
+ path);
if (!application_path) {
/* CreateProcess will fail, but this allows us to pass this error to */

0 comments on commit 8ed2ffb

Please sign in to comment.