Mercurial > hg > xemacs-beta
comparison src/ntproc.c @ 100:4be1180a9e89 r20-1b2
Import from CVS: tag r20-1b2
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:15:11 +0200 |
parents | |
children | 9b50b4588a93 |
comparison
equal
deleted
inserted
replaced
99:2d83cbd90d8d | 100:4be1180a9e89 |
---|---|
1 /* Process support for Windows NT port of XEMACS. | |
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. | |
20 | |
21 Drew Bliss Oct 14, 1993 | |
22 Adapted from alarm.c by Tim Fleehart */ | |
23 | |
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ | |
25 | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 #include <errno.h> | |
29 #include <io.h> | |
30 #include <fcntl.h> | |
31 #include <signal.h> | |
32 | |
33 /* must include CRT headers *before* config.h */ | |
34 #include "config.h" | |
35 #undef signal | |
36 #undef wait | |
37 #undef spawnve | |
38 #undef select | |
39 #undef kill | |
40 | |
41 #include <windows.h> | |
42 | |
43 #include "lisp.h" | |
44 #include "nt.h" | |
45 #include "systime.h" | |
46 #include "syswait.h" | |
47 #include "process.h" | |
48 | |
49 /* Control whether spawnve quotes arguments as necessary to ensure | |
50 correct parsing by child process. Because not all uses of spawnve | |
51 are careful about constructing argv arrays, we make this behaviour | |
52 conditional (off by default). */ | |
53 Lisp_Object Vwin32_quote_process_args; | |
54 | |
55 /* Time to sleep before reading from a subprocess output pipe - this | |
56 avoids the inefficiency of frequently reading small amounts of data. | |
57 This is primarily necessary for handling DOS processes on Windows 95, | |
58 but is useful for Win32 processes on both Win95 and NT as well. */ | |
59 Lisp_Object Vwin32_pipe_read_delay; | |
60 | |
61 /* Control conversion of upper case file names to lower case. | |
62 nil means no, t means yes. */ | |
63 Lisp_Object Vwin32_downcase_file_names; | |
64 | |
65 /* Keep track of whether we have already started a DOS program. */ | |
66 BOOL dos_process_running; | |
67 | |
68 #ifndef SYS_SIGLIST_DECLARED | |
69 extern char *sys_siglist[]; | |
70 #endif | |
71 | |
72 #ifdef EMACSDEBUG | |
73 void _DebPrint (const char *fmt, ...) | |
74 { | |
75 char buf[1024]; | |
76 va_list args; | |
77 | |
78 va_start (args, fmt); | |
79 vsprintf (buf, fmt, args); | |
80 va_end (args); | |
81 OutputDebugString (buf); | |
82 } | |
83 #endif | |
84 | |
85 typedef void (_CALLBACK_ *signal_handler)(int); | |
86 | |
87 /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ | |
88 static signal_handler sig_handlers[NSIG]; | |
89 | |
90 /* Fake signal implementation to record the SIGCHLD handler. */ | |
91 signal_handler | |
92 sys_signal (int sig, signal_handler handler) | |
93 { | |
94 signal_handler old; | |
95 | |
96 if (sig != SIGCHLD) | |
97 { | |
98 errno = EINVAL; | |
99 return SIG_ERR; | |
100 } | |
101 old = sig_handlers[sig]; | |
102 sig_handlers[sig] = handler; | |
103 return old; | |
104 } | |
105 | |
106 /* Defined in <process.h> which conflicts with the local copy */ | |
107 #define _P_NOWAIT 1 | |
108 | |
109 /* Child process management list. */ | |
110 int child_proc_count = 0; | |
111 child_process child_procs[ MAX_CHILDREN ]; | |
112 child_process *dead_child = NULL; | |
113 | |
114 DWORD WINAPI reader_thread (void *arg); | |
115 | |
116 /* Find an unused process slot. */ | |
117 child_process * | |
118 new_child (void) | |
119 { | |
120 child_process *cp; | |
121 DWORD id; | |
122 | |
123 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
124 if (!CHILD_ACTIVE (cp)) | |
125 goto Initialise; | |
126 if (child_proc_count == MAX_CHILDREN) | |
127 return NULL; | |
128 cp = &child_procs[child_proc_count++]; | |
129 | |
130 Initialise: | |
131 memset (cp, 0, sizeof(*cp)); | |
132 cp->fd = -1; | |
133 cp->pid = -1; | |
134 cp->procinfo.hProcess = NULL; | |
135 cp->status = STATUS_READ_ERROR; | |
136 | |
137 /* use manual reset event so that select() will function properly */ | |
138 cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL); | |
139 if (cp->char_avail) | |
140 { | |
141 cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL); | |
142 if (cp->char_consumed) | |
143 { | |
144 cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id); | |
145 if (cp->thrd) | |
146 return cp; | |
147 } | |
148 } | |
149 delete_child (cp); | |
150 return NULL; | |
151 } | |
152 | |
153 void | |
154 delete_child (child_process *cp) | |
155 { | |
156 int i; | |
157 | |
158 /* Should not be deleting a child that is still needed. */ | |
159 for (i = 0; i < MAXDESC; i++) | |
160 if (fd_info[i].cp == cp) | |
161 abort (); | |
162 | |
163 if (!CHILD_ACTIVE (cp)) | |
164 return; | |
165 | |
166 /* reap thread if necessary */ | |
167 if (cp->thrd) | |
168 { | |
169 DWORD rc; | |
170 | |
171 if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE) | |
172 { | |
173 /* let the thread exit cleanly if possible */ | |
174 cp->status = STATUS_READ_ERROR; | |
175 SetEvent (cp->char_consumed); | |
176 if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0) | |
177 { | |
178 DebPrint (("delete_child.WaitForSingleObject (thread) failed " | |
179 "with %lu for fd %ld\n", GetLastError (), cp->fd)); | |
180 TerminateThread (cp->thrd, 0); | |
181 } | |
182 } | |
183 CloseHandle (cp->thrd); | |
184 cp->thrd = NULL; | |
185 } | |
186 if (cp->char_avail) | |
187 { | |
188 CloseHandle (cp->char_avail); | |
189 cp->char_avail = NULL; | |
190 } | |
191 if (cp->char_consumed) | |
192 { | |
193 CloseHandle (cp->char_consumed); | |
194 cp->char_consumed = NULL; | |
195 } | |
196 | |
197 /* update child_proc_count (highest numbered slot in use plus one) */ | |
198 if (cp == child_procs + child_proc_count - 1) | |
199 { | |
200 for (i = child_proc_count-1; i >= 0; i--) | |
201 if (CHILD_ACTIVE (&child_procs[i])) | |
202 { | |
203 child_proc_count = i + 1; | |
204 break; | |
205 } | |
206 } | |
207 if (i < 0) | |
208 child_proc_count = 0; | |
209 } | |
210 | |
211 /* Find a child by pid. */ | |
212 static child_process * | |
213 find_child_pid (DWORD pid) | |
214 { | |
215 child_process *cp; | |
216 | |
217 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
218 if (CHILD_ACTIVE (cp) && pid == cp->pid) | |
219 return cp; | |
220 return NULL; | |
221 } | |
222 | |
223 | |
224 /* Thread proc for child process and socket reader threads. Each thread | |
225 is normally blocked until woken by select() to check for input by | |
226 reading one char. When the read completes, char_avail is signalled | |
227 to wake up the select emulator and the thread blocks itself again. */ | |
228 DWORD WINAPI | |
229 reader_thread (void *arg) | |
230 { | |
231 child_process *cp; | |
232 | |
233 /* Our identity */ | |
234 cp = (child_process *)arg; | |
235 | |
236 /* We have to wait for the go-ahead before we can start */ | |
237 if (cp == NULL || | |
238 WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) | |
239 return 1; | |
240 | |
241 for (;;) | |
242 { | |
243 int rc; | |
244 | |
245 rc = _sys_read_ahead (cp->fd); | |
246 | |
247 /* The name char_avail is a misnomer - it really just means the | |
248 read-ahead has completed, whether successfully or not. */ | |
249 if (!SetEvent (cp->char_avail)) | |
250 { | |
251 DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n", | |
252 GetLastError (), cp->fd)); | |
253 return 1; | |
254 } | |
255 | |
256 if (rc == STATUS_READ_ERROR) | |
257 return 1; | |
258 | |
259 /* If the read died, the child has died so let the thread die */ | |
260 if (rc == STATUS_READ_FAILED) | |
261 break; | |
262 | |
263 /* Wait until our input is acknowledged before reading again */ | |
264 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) | |
265 { | |
266 DebPrint (("reader_thread.WaitForSingleObject failed with " | |
267 "%lu for fd %ld\n", GetLastError (), cp->fd)); | |
268 break; | |
269 } | |
270 } | |
271 return 0; | |
272 } | |
273 | |
274 static BOOL | |
275 create_child (char *exe, char *cmdline, char *env, | |
276 int * pPid, child_process *cp) | |
277 { | |
278 STARTUPINFO start; | |
279 SECURITY_ATTRIBUTES sec_attrs; | |
280 SECURITY_DESCRIPTOR sec_desc; | |
281 | |
282 if (cp == NULL) abort (); | |
283 | |
284 memset (&start, 0, sizeof (start)); | |
285 start.cb = sizeof (start); | |
286 | |
287 #ifdef HAVE_NTGUI | |
288 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
289 start.wShowWindow = SW_HIDE; | |
290 | |
291 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE); | |
292 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); | |
293 start.hStdError = GetStdHandle (STD_ERROR_HANDLE); | |
294 #endif /* HAVE_NTGUI */ | |
295 | |
296 /* Explicitly specify no security */ | |
297 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION)) | |
298 goto EH_Fail; | |
299 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE)) | |
300 goto EH_Fail; | |
301 sec_attrs.nLength = sizeof (sec_attrs); | |
302 sec_attrs.lpSecurityDescriptor = &sec_desc; | |
303 sec_attrs.bInheritHandle = FALSE; | |
304 | |
305 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, | |
306 CREATE_NEW_PROCESS_GROUP, | |
307 env, NULL, | |
308 &start, &cp->procinfo)) | |
309 goto EH_Fail; | |
310 | |
311 cp->pid = (int) cp->procinfo.dwProcessId; | |
312 | |
313 /* Hack for Windows 95, which assigns large (ie negative) pids */ | |
314 if (cp->pid < 0) | |
315 cp->pid = -cp->pid; | |
316 | |
317 /* pid must fit in a Lisp_Int */ | |
318 cp->pid = (cp->pid & VALMASK); | |
319 | |
320 | |
321 *pPid = cp->pid; | |
322 | |
323 return TRUE; | |
324 | |
325 EH_Fail: | |
326 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError());); | |
327 return FALSE; | |
328 } | |
329 | |
330 /* create_child doesn't know what emacs' file handle will be for waiting | |
331 on output from the child, so we need to make this additional call | |
332 to register the handle with the process | |
333 This way the select emulator knows how to match file handles with | |
334 entries in child_procs. */ | |
335 void | |
336 register_child (int pid, int fd) | |
337 { | |
338 child_process *cp; | |
339 | |
340 cp = find_child_pid (pid); | |
341 if (cp == NULL) | |
342 { | |
343 DebPrint (("register_child unable to find pid %lu\n", pid)); | |
344 return; | |
345 } | |
346 | |
347 #ifdef FULL_DEBUG | |
348 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid)); | |
349 #endif | |
350 | |
351 cp->fd = fd; | |
352 | |
353 /* thread is initially blocked until select is called; set status so | |
354 that select will release thread */ | |
355 cp->status = STATUS_READ_ACKNOWLEDGED; | |
356 | |
357 /* attach child_process to fd_info */ | |
358 if (fd_info[fd].cp != NULL) | |
359 { | |
360 DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd)); | |
361 abort (); | |
362 } | |
363 | |
364 fd_info[fd].cp = cp; | |
365 } | |
366 | |
367 /* When a process dies its pipe will break so the reader thread will | |
368 signal failure to the select emulator. | |
369 The select emulator then calls this routine to clean up. | |
370 Since the thread signaled failure we can assume it is exiting. */ | |
371 static void | |
372 reap_subprocess (child_process *cp) | |
373 { | |
374 if (cp->procinfo.hProcess) | |
375 { | |
376 /* Reap the process */ | |
377 if (WaitForSingleObject (cp->procinfo.hProcess, INFINITE) != WAIT_OBJECT_0) | |
378 DebPrint (("reap_subprocess.WaitForSingleObject (process) failed " | |
379 "with %lu for fd %ld\n", GetLastError (), cp->fd)); | |
380 CloseHandle (cp->procinfo.hProcess); | |
381 cp->procinfo.hProcess = NULL; | |
382 CloseHandle (cp->procinfo.hThread); | |
383 cp->procinfo.hThread = NULL; | |
384 | |
385 /* If this was a DOS process, indicate that it is now safe to | |
386 start a new one. */ | |
387 if (cp->is_dos_process) | |
388 dos_process_running = FALSE; | |
389 } | |
390 | |
391 /* For asynchronous children, the child_proc resources will be freed | |
392 when the last pipe read descriptor is closed; for synchronous | |
393 children, we must explicitly free the resources now because | |
394 register_child has not been called. */ | |
395 if (cp->fd == -1) | |
396 delete_child (cp); | |
397 } | |
398 | |
399 /* Wait for any of our existing child processes to die | |
400 When it does, close its handle | |
401 Return the pid and fill in the status if non-NULL. */ | |
402 | |
403 int | |
404 sys_wait (int *status) | |
405 { | |
406 DWORD active, retval; | |
407 int nh; | |
408 int pid; | |
409 child_process *cp, *cps[MAX_CHILDREN]; | |
410 HANDLE wait_hnd[MAX_CHILDREN]; | |
411 | |
412 nh = 0; | |
413 if (dead_child != NULL) | |
414 { | |
415 /* We want to wait for a specific child */ | |
416 wait_hnd[nh] = dead_child->procinfo.hProcess; | |
417 cps[nh] = dead_child; | |
418 if (!wait_hnd[nh]) abort (); | |
419 nh++; | |
420 } | |
421 else | |
422 { | |
423 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
424 /* some child_procs might be sockets; ignore them */ | |
425 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess) | |
426 { | |
427 wait_hnd[nh] = cp->procinfo.hProcess; | |
428 cps[nh] = cp; | |
429 if (!wait_hnd[nh]) abort (); | |
430 nh++; | |
431 } | |
432 } | |
433 | |
434 if (nh == 0) | |
435 { | |
436 /* Nothing to wait on, so fail */ | |
437 errno = ECHILD; | |
438 return -1; | |
439 } | |
440 | |
441 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, INFINITE); | |
442 if (active == WAIT_FAILED) | |
443 { | |
444 errno = EBADF; | |
445 return -1; | |
446 } | |
447 else if (active == WAIT_TIMEOUT) | |
448 { | |
449 /* Should never happen */ | |
450 errno = EINVAL; | |
451 return -1; | |
452 } | |
453 else if (active >= WAIT_OBJECT_0 && | |
454 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) | |
455 { | |
456 active -= WAIT_OBJECT_0; | |
457 } | |
458 else if (active >= WAIT_ABANDONED_0 && | |
459 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | |
460 { | |
461 active -= WAIT_ABANDONED_0; | |
462 } | |
463 | |
464 if (!GetExitCodeProcess (wait_hnd[active], &retval)) | |
465 { | |
466 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n", | |
467 GetLastError ())); | |
468 retval = 1; | |
469 } | |
470 if (retval == STILL_ACTIVE) | |
471 { | |
472 /* Should never happen */ | |
473 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); | |
474 errno = EINVAL; | |
475 return -1; | |
476 } | |
477 | |
478 /* Massage the exit code from the process to match the format expected | |
479 by the WIFSTOPPED et al macros in syswait.h. Only WIFSIGNALED and | |
480 WIFEXITED are supported; WIFSTOPPED doesn't make sense under NT. */ | |
481 | |
482 if (retval == STATUS_CONTROL_C_EXIT) | |
483 retval = SIGINT; | |
484 else | |
485 retval <<= 8; | |
486 | |
487 cp = cps[active]; | |
488 pid = cp->pid; | |
489 #ifdef FULL_DEBUG | |
490 DebPrint (("Wait signaled with process pid %d\n", cp->pid)); | |
491 #endif | |
492 | |
493 if (status) | |
494 { | |
495 *status = retval; | |
496 } | |
497 else if (synch_process_alive) | |
498 { | |
499 synch_process_alive = 0; | |
500 | |
501 /* Report the status of the synchronous process. */ | |
502 if (WIFEXITED (retval)) | |
503 synch_process_retcode = WRETCODE (retval); | |
504 else if (WIFSIGNALED (retval)) | |
505 { | |
506 int code = WTERMSIG (retval); | |
507 char *signame = 0; | |
508 | |
509 if (code < NSIG) | |
510 { | |
511 /* Suppress warning if the table has const char *. */ | |
512 signame = (char *) sys_siglist[code]; | |
513 } | |
514 if (signame == 0) | |
515 signame = "unknown"; | |
516 | |
517 synch_process_death = signame; | |
518 } | |
519 | |
520 reap_subprocess (cp); | |
521 } | |
522 | |
523 return pid; | |
524 } | |
525 | |
526 int | |
527 win32_is_dos_binary (char * filename) | |
528 { | |
529 IMAGE_DOS_HEADER dos_header; | |
530 DWORD signature; | |
531 int fd; | |
532 int is_dos_binary = FALSE; | |
533 | |
534 fd = open (filename, O_RDONLY | O_BINARY, 0); | |
535 if (fd >= 0) | |
536 { | |
537 char * p = strrchr (filename, '.'); | |
538 | |
539 /* We can only identify DOS .com programs from the extension. */ | |
540 if (p && stricmp (p, ".com") == 0) | |
541 is_dos_binary = TRUE; | |
542 else if (p && stricmp (p, ".bat") == 0) | |
543 { | |
544 /* A DOS shell script - it appears that CreateProcess is happy | |
545 to accept this (somewhat surprisingly); presumably it looks | |
546 at COMSPEC to determine what executable to actually invoke. | |
547 Therefore, we have to do the same here as well. */ | |
548 p = getenv ("COMSPEC"); | |
549 if (p) | |
550 is_dos_binary = win32_is_dos_binary (p); | |
551 } | |
552 else | |
553 { | |
554 /* Look for DOS .exe signature - if found, we must also check | |
555 that it isn't really a 16- or 32-bit Windows exe, since | |
556 both formats start with a DOS program stub. Note that | |
557 16-bit Windows executables use the OS/2 1.x format. */ | |
558 if (read (fd, &dos_header, sizeof (dos_header)) == sizeof (dos_header) | |
559 && dos_header.e_magic == IMAGE_DOS_SIGNATURE | |
560 && lseek (fd, dos_header.e_lfanew, SEEK_SET) != -1) | |
561 { | |
562 if (read (fd, &signature, sizeof (signature)) != sizeof (signature) | |
563 || (signature != IMAGE_NT_SIGNATURE && | |
564 LOWORD (signature) != IMAGE_OS2_SIGNATURE)) | |
565 is_dos_binary = TRUE; | |
566 } | |
567 } | |
568 close (fd); | |
569 } | |
570 | |
571 return is_dos_binary; | |
572 } | |
573 | |
574 /* We pass our process ID to our children by setting up an environment | |
575 variable in their environment. */ | |
576 char ppid_env_var_buffer[64]; | |
577 | |
578 /* When a new child process is created we need to register it in our list, | |
579 so intercept spawn requests. */ | |
580 int | |
581 sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |
582 { | |
583 Lisp_Object program, full; | |
584 char *cmdline, *env, *parg, **targ; | |
585 int arglen; | |
586 int pid; | |
587 child_process *cp; | |
588 int is_dos_binary; | |
589 | |
590 /* We don't care about the other modes */ | |
591 if (mode != _P_NOWAIT) | |
592 { | |
593 errno = EINVAL; | |
594 return -1; | |
595 } | |
596 | |
597 /* Handle executable names without an executable suffix. */ | |
598 program = make_string (cmdname, strlen (cmdname)); | |
599 if (NILP (Ffile_executable_p (program))) | |
600 { | |
601 struct gcpro gcpro1; | |
602 | |
603 full = Qnil; | |
604 GCPRO1 (program); | |
605 locate_file (Vexec_path, program, EXEC_SUFFIXES, &full, 1); | |
606 UNGCPRO; | |
607 if (NILP (full)) | |
608 { | |
609 errno = EINVAL; | |
610 return -1; | |
611 } | |
612 cmdname = XSTRING (full)->_data; | |
613 argv[0] = cmdname; | |
614 } | |
615 | |
616 /* make sure cmdname is in DOS format */ | |
617 strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); | |
618 unixtodos_filename (cmdname); | |
619 argv[0] = cmdname; | |
620 | |
621 /* Check if program is a DOS executable, and if so whether we are | |
622 allowed to start it. */ | |
623 is_dos_binary = win32_is_dos_binary (cmdname); | |
624 if (is_dos_binary && dos_process_running) | |
625 { | |
626 errno = EAGAIN; | |
627 return -1; | |
628 } | |
629 | |
630 /* we have to do some conjuring here to put argv and envp into the | |
631 form CreateProcess wants... argv needs to be a space separated/null | |
632 terminated list of parameters, and envp is a null | |
633 separated/double-null terminated list of parameters. | |
634 | |
635 Additionally, zero-length args and args containing whitespace need | |
636 to be wrapped in double quotes. Args containing embedded double | |
637 quotes (as opposed to enclosing quotes, which we leave alone) are | |
638 usually illegal (most Win32 programs do not implement escaping of | |
639 double quotes - sad but true, at least for programs compiled with | |
640 MSVC), but we will escape quotes anyway for those programs that can | |
641 handle it. The Win32 gcc library from Cygnus doubles quotes to | |
642 escape them, so we will use that convention. | |
643 | |
644 Since I have no idea how large argv and envp are likely to be | |
645 we figure out list lengths on the fly and allocate them. */ | |
646 | |
647 /* do argv... */ | |
648 arglen = 0; | |
649 targ = argv; | |
650 while (*targ) | |
651 { | |
652 char * p = *targ; | |
653 int add_quotes = 0; | |
654 | |
655 if (*p == 0) | |
656 add_quotes = 1; | |
657 while (*p) | |
658 if (*p++ == '"') | |
659 { | |
660 /* allow for embedded quotes to be doubled - we won't | |
661 actually double quotes that aren't embedded though */ | |
662 arglen++; | |
663 add_quotes = 1; | |
664 } | |
665 else if (*p == ' ' || *p == '\t') | |
666 add_quotes = 1; | |
667 if (add_quotes) | |
668 arglen += 2; | |
669 arglen += strlen (*targ++) + 1; | |
670 } | |
671 cmdline = alloca (arglen); | |
672 targ = argv; | |
673 parg = cmdline; | |
674 while (*targ) | |
675 { | |
676 char * p = *targ; | |
677 int add_quotes = 0; | |
678 | |
679 if (*p == 0) | |
680 add_quotes = 1; | |
681 | |
682 if (!NILP (Vwin32_quote_process_args)) | |
683 { | |
684 /* This is conditional because it sometimes causes more | |
685 problems than it solves, since argv arrays are not always | |
686 carefully constructed. M-x grep, for instance, passes the | |
687 whole command line as one argument, so it becomes | |
688 impossible to pass a regexp which contains spaces. */ | |
689 for ( ; *p; p++) | |
690 if (*p == ' ' || *p == '\t' || *p == '"') | |
691 add_quotes = 1; | |
692 } | |
693 if (add_quotes) | |
694 { | |
695 char * first; | |
696 char * last; | |
697 | |
698 p = *targ; | |
699 first = p; | |
700 last = p + strlen (p) - 1; | |
701 *parg++ = '"'; | |
702 while (*p) | |
703 { | |
704 if (*p == '"' && p > first && p < last) | |
705 *parg++ = '"'; /* double up embedded quotes only */ | |
706 *parg++ = *p++; | |
707 } | |
708 *parg++ = '"'; | |
709 } | |
710 else | |
711 { | |
712 strcpy (parg, *targ); | |
713 parg += strlen (*targ); | |
714 } | |
715 *parg++ = ' '; | |
716 targ++; | |
717 } | |
718 *--parg = '\0'; | |
719 | |
720 /* and envp... */ | |
721 arglen = 1; | |
722 targ = envp; | |
723 while (*targ) | |
724 { | |
725 arglen += strlen (*targ++) + 1; | |
726 } | |
727 sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d", | |
728 GetCurrentProcessId ()); | |
729 arglen += strlen (ppid_env_var_buffer) + 1; | |
730 | |
731 env = alloca (arglen); | |
732 targ = envp; | |
733 parg = env; | |
734 while (*targ) | |
735 { | |
736 strcpy (parg, *targ); | |
737 parg += strlen (*targ++); | |
738 *parg++ = '\0'; | |
739 } | |
740 strcpy (parg, ppid_env_var_buffer); | |
741 parg += strlen (ppid_env_var_buffer); | |
742 *parg++ = '\0'; | |
743 *parg = '\0'; | |
744 | |
745 cp = new_child (); | |
746 if (cp == NULL) | |
747 { | |
748 errno = EAGAIN; | |
749 return -1; | |
750 } | |
751 | |
752 /* Now create the process. */ | |
753 if (!create_child (cmdname, cmdline, env, &pid, cp)) | |
754 { | |
755 delete_child (cp); | |
756 errno = ENOEXEC; | |
757 return -1; | |
758 } | |
759 | |
760 if (is_dos_binary) | |
761 { | |
762 cp->is_dos_process = TRUE; | |
763 dos_process_running = TRUE; | |
764 } | |
765 | |
766 return pid; | |
767 } | |
768 | |
769 /* Emulate the select call | |
770 Wait for available input on any of the given rfds, or timeout if | |
771 a timeout is given and no input is detected | |
772 wfds and efds are not supported and must be NULL. */ | |
773 | |
774 #if 0 | |
775 /* From ntterm.c */ | |
776 extern HANDLE keyboard_handle; | |
777 #endif | |
778 /* From process.c */ | |
779 extern int proc_buffered_char[]; | |
780 | |
781 int | |
782 sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, | |
783 EMACS_TIME *timeout) | |
784 { | |
785 SELECT_TYPE orfds; | |
786 DWORD timeout_ms; | |
787 int i, nh, nr; | |
788 DWORD active; | |
789 child_process *cp; | |
790 HANDLE wait_hnd[MAXDESC]; | |
791 int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ | |
792 | |
793 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ | |
794 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) | |
795 { | |
796 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); | |
797 return 0; | |
798 } | |
799 | |
800 /* Otherwise, we only handle rfds, so fail otherwise. */ | |
801 if (rfds == NULL || wfds != NULL || efds != NULL) | |
802 { | |
803 errno = EINVAL; | |
804 return -1; | |
805 } | |
806 | |
807 orfds = *rfds; | |
808 FD_ZERO (rfds); | |
809 nr = 0; | |
810 | |
811 /* Build a list of handles to wait on. */ | |
812 nh = 0; | |
813 for (i = 0; i < nfds; i++) | |
814 if (FD_ISSET (i, &orfds)) | |
815 { | |
816 if (i == 0) | |
817 { | |
818 #if 0 | |
819 if (keyboard_handle) | |
820 { | |
821 /* Handle stdin specially */ | |
822 wait_hnd[nh] = keyboard_handle; | |
823 fdindex[nh] = i; | |
824 nh++; | |
825 } | |
826 #endif | |
827 | |
828 /* Check for any emacs-generated input in the queue since | |
829 it won't be detected in the wait */ | |
830 if (detect_input_pending ()) | |
831 { | |
832 FD_SET (i, rfds); | |
833 return 1; | |
834 } | |
835 } | |
836 else | |
837 { | |
838 /* Child process and socket input */ | |
839 cp = fd_info[i].cp; | |
840 if (cp) | |
841 { | |
842 int current_status = cp->status; | |
843 | |
844 if (current_status == STATUS_READ_ACKNOWLEDGED) | |
845 { | |
846 /* Tell reader thread which file handle to use. */ | |
847 cp->fd = i; | |
848 /* Wake up the reader thread for this process */ | |
849 cp->status = STATUS_READ_READY; | |
850 if (!SetEvent (cp->char_consumed)) | |
851 DebPrint (("nt_select.SetEvent failed with " | |
852 "%lu for fd %ld\n", GetLastError (), i)); | |
853 } | |
854 | |
855 #ifdef CHECK_INTERLOCK | |
856 /* slightly crude cross-checking of interlock between threads */ | |
857 | |
858 current_status = cp->status; | |
859 if (WaitForSingleObject (cp->char_avail, 0) == WAIT_OBJECT_0) | |
860 { | |
861 /* char_avail has been signalled, so status (which may | |
862 have changed) should indicate read has completed | |
863 but has not been acknowledged. */ | |
864 current_status = cp->status; | |
865 if (current_status != STATUS_READ_SUCCEEDED && | |
866 current_status != STATUS_READ_FAILED) | |
867 DebPrint (("char_avail set, but read not completed: status %d\n", | |
868 current_status)); | |
869 } | |
870 else | |
871 { | |
872 /* char_avail has not been signalled, so status should | |
873 indicate that read is in progress; small possibility | |
874 that read has completed but event wasn't yet signalled | |
875 when we tested it (because a context switch occurred | |
876 or if running on separate CPUs). */ | |
877 if (current_status != STATUS_READ_READY && | |
878 current_status != STATUS_READ_IN_PROGRESS && | |
879 current_status != STATUS_READ_SUCCEEDED && | |
880 current_status != STATUS_READ_FAILED) | |
881 DebPrint (("char_avail reset, but read status is bad: %d\n", | |
882 current_status)); | |
883 } | |
884 #endif | |
885 wait_hnd[nh] = cp->char_avail; | |
886 fdindex[nh] = i; | |
887 if (!wait_hnd[nh]) abort (); | |
888 nh++; | |
889 #ifdef FULL_DEBUG | |
890 DebPrint (("select waiting on child %d fd %d\n", | |
891 cp-child_procs, i)); | |
892 #endif | |
893 } | |
894 else | |
895 { | |
896 /* Unable to find something to wait on for this fd, skip */ | |
897 DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i)); | |
898 abort (); | |
899 } | |
900 } | |
901 } | |
902 | |
903 /* Nothing to look for, so we didn't find anything */ | |
904 if (nh == 0) | |
905 { | |
906 if (timeout) | |
907 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); | |
908 return 0; | |
909 } | |
910 | |
911 /* | |
912 Wait for input | |
913 If a child process dies while this is waiting, its pipe will break | |
914 so the reader thread will signal an error condition, thus, the wait | |
915 will wake up | |
916 */ | |
917 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; | |
918 | |
919 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); | |
920 | |
921 if (active == WAIT_FAILED) | |
922 { | |
923 DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n", | |
924 nh, timeout_ms, GetLastError ())); | |
925 /* don't return EBADF - this causes wait_reading_process_input to | |
926 abort; WAIT_FAILED is returned when single-stepping under | |
927 Windows 95 after switching thread focus in debugger, and | |
928 possibly at other times. */ | |
929 errno = EINTR; | |
930 return -1; | |
931 } | |
932 else if (active == WAIT_TIMEOUT) | |
933 { | |
934 return 0; | |
935 } | |
936 else if (active >= WAIT_OBJECT_0 && | |
937 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) | |
938 { | |
939 active -= WAIT_OBJECT_0; | |
940 } | |
941 else if (active >= WAIT_ABANDONED_0 && | |
942 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | |
943 { | |
944 active -= WAIT_ABANDONED_0; | |
945 } | |
946 | |
947 /* Loop over all handles after active (now officially documented as | |
948 being the first signalled handle in the array). We do this to | |
949 ensure fairness, so that all channels with data available will be | |
950 processed - otherwise higher numbered channels could be starved. */ | |
951 do | |
952 { | |
953 if (fdindex[active] == 0) | |
954 { | |
955 /* Keyboard input available */ | |
956 FD_SET (0, rfds); | |
957 nr++; | |
958 } | |
959 else | |
960 { | |
961 /* must be a socket or pipe */ | |
962 int current_status; | |
963 | |
964 cp = fd_info[ fdindex[active] ].cp; | |
965 | |
966 /* Read ahead should have completed, either succeeding or failing. */ | |
967 FD_SET (fdindex[active], rfds); | |
968 nr++; | |
969 current_status = cp->status; | |
970 if (current_status != STATUS_READ_SUCCEEDED) | |
971 { | |
972 if (current_status != STATUS_READ_FAILED) | |
973 DebPrint (("internal error: subprocess pipe signalled " | |
974 "at the wrong time (status %d)\n!", current_status)); | |
975 | |
976 /* The child_process entry for a socket or pipe will be | |
977 freed when the last descriptor using it is closed; for | |
978 pipes, we call the SIGCHLD handler. */ | |
979 if (fd_info[ fdindex[active] ].flags & FILE_PIPE) | |
980 { | |
981 /* The SIGCHLD handler will do a Wait so we know it won't | |
982 return until the process is dead | |
983 We force Wait to only wait for this process to avoid it | |
984 picking up other children that happen to be dead but that | |
985 we haven't noticed yet | |
986 SIG_DFL for SIGCHLD is ignore? */ | |
987 if (sig_handlers[SIGCHLD] != SIG_DFL && | |
988 sig_handlers[SIGCHLD] != SIG_IGN) | |
989 { | |
990 #ifdef FULL_DEBUG | |
991 DebPrint (("select calling SIGCHLD handler for pid %d\n", | |
992 cp->pid)); | |
993 #endif | |
994 dead_child = cp; | |
995 sig_handlers[SIGCHLD] (SIGCHLD); | |
996 dead_child = NULL; | |
997 } | |
998 | |
999 /* Clean up the child process entry in the table */ | |
1000 reap_subprocess (cp); | |
1001 } | |
1002 } | |
1003 } | |
1004 | |
1005 /* Test for input on remaining channels. */ | |
1006 while (++active < nh) | |
1007 if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0) | |
1008 break; | |
1009 } while (active < nh); | |
1010 | |
1011 return nr; | |
1012 } | |
1013 | |
1014 /* Substitute for certain kill () operations */ | |
1015 int | |
1016 sys_kill (int pid, int sig) | |
1017 { | |
1018 child_process *cp; | |
1019 HANDLE proc_hand; | |
1020 int need_to_free = 0; | |
1021 int rc = 0; | |
1022 | |
1023 /* Only handle signals that will result in the process dying */ | |
1024 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) | |
1025 { | |
1026 errno = EINVAL; | |
1027 return -1; | |
1028 } | |
1029 | |
1030 cp = find_child_pid (pid); | |
1031 if (cp == NULL) | |
1032 { | |
1033 proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid); | |
1034 if (proc_hand == NULL) | |
1035 { | |
1036 errno = EPERM; | |
1037 return -1; | |
1038 } | |
1039 need_to_free = 1; | |
1040 } | |
1041 else | |
1042 { | |
1043 proc_hand = cp->procinfo.hProcess; | |
1044 pid = cp->procinfo.dwProcessId; | |
1045 } | |
1046 | |
1047 if (sig == SIGINT) | |
1048 { | |
1049 /* Ctrl-Break is NT equivalent of SIGINT. */ | |
1050 if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid)) | |
1051 { | |
1052 DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d " | |
1053 "for pid %lu\n", GetLastError (), pid)); | |
1054 errno = EINVAL; | |
1055 rc = -1; | |
1056 } | |
1057 } | |
1058 else | |
1059 { | |
1060 /* Kill the process. On Win32 this doesn't kill child processes | |
1061 so it doesn't work very well for shells which is why it's not | |
1062 used in every case. Also, don't try to terminate DOS processes | |
1063 (on Win95), because this will hang Emacs. */ | |
1064 if (!(cp && cp->is_dos_process) | |
1065 && !TerminateProcess (proc_hand, 0xff)) | |
1066 { | |
1067 DebPrint (("sys_kill.TerminateProcess returned %d " | |
1068 "for pid %lu\n", GetLastError (), pid)); | |
1069 errno = EINVAL; | |
1070 rc = -1; | |
1071 } | |
1072 } | |
1073 | |
1074 if (need_to_free) | |
1075 CloseHandle (proc_hand); | |
1076 | |
1077 return rc; | |
1078 } | |
1079 | |
1080 #if 0 | |
1081 extern int report_file_error (CONST char *, Lisp_Object); | |
1082 #endif | |
1083 /* The following two routines are used to manipulate stdin, stdout, and | |
1084 stderr of our child processes. | |
1085 | |
1086 Assuming that in, out, and err are *not* inheritable, we make them | |
1087 stdin, stdout, and stderr of the child as follows: | |
1088 | |
1089 - Save the parent's current standard handles. | |
1090 - Set the std handles to inheritable duplicates of the ones being passed in. | |
1091 (Note that _get_osfhandle() is an io.h procedure that retrieves the | |
1092 NT file handle for a crt file descriptor.) | |
1093 - Spawn the child, which inherits in, out, and err as stdin, | |
1094 stdout, and stderr. (see Spawnve) | |
1095 - Close the std handles passed to the child. | |
1096 - Reset the parent's standard handles to the saved handles. | |
1097 (see reset_standard_handles) | |
1098 We assume that the caller closes in, out, and err after calling us. */ | |
1099 | |
1100 void | |
1101 prepare_standard_handles (int in, int out, int err, HANDLE handles[3]) | |
1102 { | |
1103 HANDLE parent; | |
1104 HANDLE newstdin, newstdout, newstderr; | |
1105 | |
1106 parent = GetCurrentProcess (); | |
1107 | |
1108 handles[0] = GetStdHandle (STD_INPUT_HANDLE); | |
1109 handles[1] = GetStdHandle (STD_OUTPUT_HANDLE); | |
1110 handles[2] = GetStdHandle (STD_ERROR_HANDLE); | |
1111 | |
1112 /* make inheritable copies of the new handles */ | |
1113 if (!DuplicateHandle (parent, | |
1114 (HANDLE) _get_osfhandle (in), | |
1115 parent, | |
1116 &newstdin, | |
1117 0, | |
1118 TRUE, | |
1119 DUPLICATE_SAME_ACCESS)) | |
1120 report_file_error ("Duplicating input handle for child", Qnil); | |
1121 | |
1122 if (!DuplicateHandle (parent, | |
1123 (HANDLE) _get_osfhandle (out), | |
1124 parent, | |
1125 &newstdout, | |
1126 0, | |
1127 TRUE, | |
1128 DUPLICATE_SAME_ACCESS)) | |
1129 report_file_error ("Duplicating output handle for child", Qnil); | |
1130 | |
1131 if (!DuplicateHandle (parent, | |
1132 (HANDLE) _get_osfhandle (err), | |
1133 parent, | |
1134 &newstderr, | |
1135 0, | |
1136 TRUE, | |
1137 DUPLICATE_SAME_ACCESS)) | |
1138 report_file_error ("Duplicating error handle for child", Qnil); | |
1139 | |
1140 /* and store them as our std handles */ | |
1141 if (!SetStdHandle (STD_INPUT_HANDLE, newstdin)) | |
1142 report_file_error ("Changing stdin handle", Qnil); | |
1143 | |
1144 if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout)) | |
1145 report_file_error ("Changing stdout handle", Qnil); | |
1146 | |
1147 if (!SetStdHandle (STD_ERROR_HANDLE, newstderr)) | |
1148 report_file_error ("Changing stderr handle", Qnil); | |
1149 } | |
1150 | |
1151 void | |
1152 reset_standard_handles (int in, int out, int err, HANDLE handles[3]) | |
1153 { | |
1154 /* close the duplicated handles passed to the child */ | |
1155 CloseHandle (GetStdHandle (STD_INPUT_HANDLE)); | |
1156 CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE)); | |
1157 CloseHandle (GetStdHandle (STD_ERROR_HANDLE)); | |
1158 | |
1159 /* now restore parent's saved std handles */ | |
1160 SetStdHandle (STD_INPUT_HANDLE, handles[0]); | |
1161 SetStdHandle (STD_OUTPUT_HANDLE, handles[1]); | |
1162 SetStdHandle (STD_ERROR_HANDLE, handles[2]); | |
1163 } | |
1164 | |
1165 #ifdef HAVE_SOCKETS | |
1166 | |
1167 /* To avoid problems with winsock implementations that work over dial-up | |
1168 connections causing or requiring a connection to exist while Emacs is | |
1169 running, Emacs no longer automatically loads winsock on startup if it | |
1170 is present. Instead, it will be loaded when open-network-stream is | |
1171 first called. | |
1172 | |
1173 To allow full control over when winsock is loaded, we provide these | |
1174 two functions to dynamically load and unload winsock. This allows | |
1175 dial-up users to only be connected when they actually need to use | |
1176 socket services. */ | |
1177 | |
1178 /* From nt.c */ | |
1179 extern HANDLE winsock_lib; | |
1180 extern BOOL term_winsock (void); | |
1181 extern BOOL init_winsock (int load_now); | |
1182 | |
1183 extern Lisp_Object Vsystem_name; | |
1184 | |
1185 DEFUN ("win32-has-winsock", Fwin32_has_winsock, 0, 1, "", /* | |
1186 Test for presence of the Windows socket library `winsock'. | |
1187 Returns non-nil if winsock support is present, nil otherwise. | |
1188 | |
1189 If the optional argument LOAD-NOW is non-nil, the winsock library is | |
1190 also loaded immediately if not already loaded. If winsock is loaded, | |
1191 the winsock local hostname is returned (since this may be different from | |
1192 the value of `system-name' and should supplant it), otherwise t is | |
1193 returned to indicate winsock support is present. | |
1194 */ | |
1195 (load_now)) | |
1196 { | |
1197 int have_winsock; | |
1198 | |
1199 have_winsock = init_winsock (!NILP (load_now)); | |
1200 if (have_winsock) | |
1201 { | |
1202 if (winsock_lib != NULL) | |
1203 { | |
1204 /* Return new value for system-name. The best way to do this | |
1205 is to call init_system_name, saving and restoring the | |
1206 original value to avoid side-effects. */ | |
1207 Lisp_Object orig_hostname = Vsystem_name; | |
1208 Lisp_Object hostname; | |
1209 | |
1210 init_system_name (); | |
1211 hostname = Vsystem_name; | |
1212 Vsystem_name = orig_hostname; | |
1213 return hostname; | |
1214 } | |
1215 return Qt; | |
1216 } | |
1217 return Qnil; | |
1218 } | |
1219 | |
1220 DEFUN ("win32-unload-winsock", Fwin32_unload_winsock, 0, 0, "", /* | |
1221 Unload the Windows socket library `winsock' if loaded. | |
1222 This is provided to allow dial-up socket connections to be disconnected | |
1223 when no longer needed. Returns nil without unloading winsock if any | |
1224 socket connections still exist. | |
1225 */ | |
1226 ()) | |
1227 { | |
1228 return term_winsock () ? Qt : Qnil; | |
1229 } | |
1230 | |
1231 #endif /* HAVE_SOCKETS */ | |
1232 | |
1233 | |
1234 syms_of_ntproc () | |
1235 { | |
1236 #ifdef HAVE_SOCKETS | |
1237 DEFSUBR (Fwin32_has_winsock); | |
1238 DEFSUBR (Fwin32_unload_winsock); | |
1239 #endif | |
1240 | |
1241 DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* | |
1242 Non-nil enables quoting of process arguments to ensure correct parsing. | |
1243 Because Windows does not directly pass argv arrays to child processes, | |
1244 programs have to reconstruct the argv array by parsing the command | |
1245 line string. For an argument to contain a space, it must be enclosed | |
1246 in double quotes or it will be parsed as multiple arguments. | |
1247 | |
1248 However, the argument list to call-process is not always correctly | |
1249 constructed (or arguments have already been quoted), so enabling this | |
1250 option may cause unexpected behavior.*/ ); | |
1251 Vwin32_quote_process_args = Qnil; | |
1252 | |
1253 DEFVAR_INT ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* | |
1254 Forced delay before reading subprocess output. | |
1255 This is done to improve the buffering of subprocess output, by | |
1256 avoiding the inefficiency of frequently reading small amounts of data. | |
1257 | |
1258 If positive, the value is the number of milliseconds to sleep before | |
1259 reading the subprocess output. If negative, the magnitude is the number | |
1260 of time slices to wait (effectively boosting the priority of the child | |
1261 process temporarily). A value of zero disables waiting entirely.*/ ); | |
1262 Vwin32_pipe_read_delay = 50; | |
1263 | |
1264 DEFVAR_LISP ("win32-downcase-file-names", &Vwin32_downcase_file_names /* | |
1265 Non-nil means convert all-upper case file names to lower case. | |
1266 This applies when performing completions and file name expansion.*/ ); | |
1267 Vwin32_downcase_file_names = Qnil; | |
1268 } | |
1269 /* end of ntproc.c */ |