@@ -51,9 +51,6 @@ typedef struct env_var {
51
51
}
52
52
53
53
54
- static const wchar_t DEFAULT_PATH_EXT [10 ] = L".COM;.EXE" ;
55
-
56
-
57
54
static void uv_process_init (uv_process_t * handle ) {
58
55
handle -> type = UV_PROCESS ;
59
56
handle -> flags = 0 ;
@@ -153,10 +150,14 @@ static wchar_t* search_path_join_test(const wchar_t* dir,
153
150
wcsncpy (result_pos , name , name_len );
154
151
result_pos += name_len ;
155
152
156
- /* Copy extension */
157
153
if (ext_len ) {
158
- result_pos [0 ] = L'.' ;
159
- result_pos ++ ;
154
+ /* Add a dot if the filename didn't end with one */
155
+ if (name_len && result_pos [-1 ] != '.' ) {
156
+ result_pos [0 ] = L'.' ;
157
+ result_pos ++ ;
158
+ }
159
+
160
+ /* Copy extension */
160
161
wcsncpy (result_pos , ext , ext_len );
161
162
result_pos += ext_len ;
162
163
}
@@ -185,54 +186,39 @@ static wchar_t* path_search_walk_ext(const wchar_t *dir,
185
186
int name_len ,
186
187
wchar_t * cwd ,
187
188
int cwd_len ,
188
- const wchar_t * path_ext ,
189
189
int name_has_ext ) {
190
- wchar_t * result = NULL ;
191
-
192
- const wchar_t * ext_start ,
193
- * ext_end = path_ext ;
190
+ wchar_t * result ;
194
191
195
- /* If the name itself has a nonemtpy extension, try this extension first */
192
+ /* If the name itself has a nonempty extension, try this extension first */
196
193
if (name_has_ext ) {
197
194
result = search_path_join_test (dir , dir_len ,
198
195
name , name_len ,
199
196
L"" , 0 ,
200
197
cwd , cwd_len );
201
- }
202
-
203
- /* Add path_ext extensions and try to find a name that matches */
204
- while (result == NULL ) {
205
- if (* ext_end == L'\0' ) {
206
- break ;
207
- }
208
-
209
- /* Skip the separator that ext_end now points to */
210
- if (ext_end != path_ext ) {
211
- ext_end ++ ;
198
+ if (result != NULL ) {
199
+ return result ;
212
200
}
201
+ }
213
202
214
- /* Find the next dot in path_ext */
215
- ext_start = wcschr (ext_end , L'.' );
216
- if (ext_start == NULL ) {
217
- break ;
218
- }
219
-
220
- /* Skip the dot */
221
- ext_start ++ ;
222
-
223
- /* Slice until we found a ; or alternatively a \0 */
224
- ext_end = wcschr (ext_start , L';' );
225
- if (ext_end == NULL ) {
226
- ext_end = wcschr (ext_start , '\0' );
227
- }
203
+ /* Try .com extension */
204
+ result = search_path_join_test (dir , dir_len ,
205
+ name , name_len ,
206
+ L"com" , 3 ,
207
+ cwd , cwd_len );
208
+ if (result != NULL ) {
209
+ return result ;
210
+ }
228
211
229
- result = search_path_join_test (dir , dir_len ,
230
- name , name_len ,
231
- ext_start , (ext_end - ext_start ),
232
- cwd , cwd_len );
212
+ /* Try .exe extension */
213
+ result = search_path_join_test (dir , dir_len ,
214
+ name , name_len ,
215
+ L"exe" , 3 ,
216
+ cwd , cwd_len );
217
+ if (result != NULL ) {
218
+ return result ;
233
219
}
234
220
235
- return result ;
221
+ return NULL ;
236
222
}
237
223
238
224
@@ -243,35 +229,28 @@ static wchar_t* path_search_walk_ext(const wchar_t *dir,
243
229
*
244
230
* It tries to return an absolute filename.
245
231
*
246
- * Furthermore, it tries to follow the semantics that cmd.exe uses as closely
247
- * as possible:
232
+ * Furthermore, it tries to follow the semantics that cmd.exe, with this
233
+ * exception that PATHEXT environment variable isn't used. Since CreateProcess
234
+ * can start only .com and .exe files, only those extensions are tried. This
235
+ * behavior equals that of msvcrt's spawn functions.
248
236
*
249
237
* - Do not search the path if the filename already contains a path (either
250
238
* relative or absolute).
251
- * (but do use path_ext)
252
239
*
253
240
* - If there's really only a filename, check the current directory for file,
254
241
* then search all path directories.
255
242
*
256
- * - If filename specifies has *any* extension, search for the file with the
243
+ * - If filename specified has *any* extension, search for the file with the
257
244
* specified extension first.
258
- * (not necessary an executable one or one that appears in path_ext;
259
- * *but* no extension or just a dot is *not* allowed)
260
245
*
261
246
* - If the literal filename is not found in a directory, try *appending*
262
- * (not replacing) extensions from path_ext in the specified order.
263
- * (an extension consisting of just a dot *may* appear in path_ext;
264
- * unlike what happens if the specified filename ends with a dot,
265
- * if path_ext specifies a single dot cmd.exe *does* look for an
266
- * extension-less file)
247
+ * (not replacing) .com first and then .exe.
267
248
*
268
249
* - The path variable may contain relative paths; relative paths are relative
269
250
* to the cwd.
270
251
*
271
252
* - Directories in path may or may not end with a trailing backslash.
272
253
*
273
- * - Extensions path_ext portions must always start with a dot.
274
- *
275
254
* - CMD does not trim leading/trailing whitespace from path/pathex entries
276
255
* nor from the environment variables as a whole.
277
256
*
@@ -281,13 +260,10 @@ static wchar_t* path_search_walk_ext(const wchar_t *dir,
281
260
* continue searching.
282
261
*
283
262
* TODO: correctly interpret UNC paths
284
- * TODO: check with cmd what should happen when a pathext entry does not start
285
- * with a dot
286
263
*/
287
264
static wchar_t * search_path (const wchar_t * file ,
288
265
wchar_t * cwd ,
289
- const wchar_t * path ,
290
- const wchar_t * path_ext ) {
266
+ const wchar_t * path ) {
291
267
int file_has_dir ;
292
268
wchar_t * result = NULL ;
293
269
wchar_t * file_name_start ;
@@ -320,12 +296,12 @@ static wchar_t* search_path(const wchar_t *file,
320
296
name_has_ext = (dot != NULL && dot [1 ] != L'\0' );
321
297
322
298
if (file_has_dir ) {
323
- /* The file has a path inside, don't use path (but do use path_ex) */
299
+ /* The file has a path inside, don't use path */
324
300
result = path_search_walk_ext (
325
301
file , file_name_start - file ,
326
302
file_name_start , file_len - (file_name_start - file ),
327
303
cwd , cwd_len ,
328
- path_ext , name_has_ext );
304
+ name_has_ext );
329
305
330
306
} else {
331
307
const wchar_t * dir_start ,
@@ -335,7 +311,7 @@ static wchar_t* search_path(const wchar_t *file,
335
311
result = path_search_walk_ext (L"" , 0 ,
336
312
file , file_len ,
337
313
cwd , cwd_len ,
338
- path_ext , name_has_ext );
314
+ name_has_ext );
339
315
340
316
while (result == NULL ) {
341
317
if (* dir_end == L'\0' ) {
@@ -364,7 +340,7 @@ static wchar_t* search_path(const wchar_t *file,
364
340
result = path_search_walk_ext (dir_start , dir_end - dir_start ,
365
341
file , file_len ,
366
342
cwd , cwd_len ,
367
- path_ext , name_has_ext );
343
+ name_has_ext );
368
344
}
369
345
}
370
346
@@ -381,7 +357,7 @@ wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
381
357
i , quote_hit ;
382
358
wchar_t * start ;
383
359
384
- /*
360
+ /*
385
361
* Check if the string must be quoted;
386
362
* if unnecessary, don't do it, it may only confuse older programs.
387
363
*/
@@ -397,7 +373,7 @@ wchar_t* quote_cmd_arg(const wchar_t *source, wchar_t *target) {
397
373
}
398
374
399
375
if (NULL == wcspbrk (source , L"\"\\" )) {
400
- /*
376
+ /*
401
377
* No embedded double quotes or backlashes, so I can just wrap
402
378
* quote marks around the whole thing.
403
379
*/
@@ -468,7 +444,7 @@ wchar_t* make_program_args(char** args, int verbatim_arguments) {
468
444
arg_count ++ ;
469
445
}
470
446
471
- /* Adjust for potential quotes. Also assume the worst-case scenario
447
+ /* Adjust for potential quotes. Also assume the worst-case scenario
472
448
/* that every character needs escaping, so we need twice as much space. */
473
449
size = size * 2 + arg_count * 2 ;
474
450
@@ -511,7 +487,7 @@ wchar_t* make_program_args(char** args, int verbatim_arguments) {
511
487
* If we learn that people are passing in huge environment blocks
512
488
* then we should probably qsort() the array and then bsearch()
513
489
* to see if it contains this variable. But there are ownership
514
- * issues associated with that solution; this is the caller's
490
+ * issues associated with that solution; this is the caller's
515
491
* char**, and modifying it is rude.
516
492
*/
517
493
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
529
505
* The way windows takes environment variables is different than what C does;
530
506
* Windows wants a contiguous block of null-terminated strings, terminated
531
507
* with an additional null.
532
- *
508
+ *
533
509
* Windows has a few "essential" environment variables. winsock will fail
534
510
* to initialize if SYSTEMROOT is not defined; some APIs make reference to
535
511
* 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) {
858
834
859
835
application_path = search_path (application ,
860
836
cwd ,
861
- path ,
862
- DEFAULT_PATH_EXT );
837
+ path );
863
838
864
839
if (!application_path ) {
865
840
/* CreateProcess will fail, but this allows us to pass this error to */
0 commit comments