Mercurial > hg > xemacs-beta
comparison src/ntproc.c @ 209:41ff10fd062f r20-4b3
Import from CVS: tag r20-4b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:04:58 +0200 |
parents | 9b50b4588a93 |
children | 2c611d1463a6 |
comparison
equal
deleted
inserted
replaced
208:f427b8ec4379 | 209:41ff10fd062f |
---|---|
20 | 20 |
21 Drew Bliss Oct 14, 1993 | 21 Drew Bliss Oct 14, 1993 |
22 Adapted from alarm.c by Tim Fleehart */ | 22 Adapted from alarm.c by Tim Fleehart */ |
23 | 23 |
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ | 24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ |
25 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ | |
25 | 26 |
26 #include <stdio.h> | 27 #include <stdio.h> |
27 #include <stdlib.h> | 28 #include <stdlib.h> |
28 #include <errno.h> | 29 #include <errno.h> |
29 #include <io.h> | 30 #include <io.h> |
40 | 41 |
41 #include <windows.h> | 42 #include <windows.h> |
42 | 43 |
43 #include "lisp.h" | 44 #include "lisp.h" |
44 #include "nt.h" | 45 #include "nt.h" |
46 #include "ntheap.h" /* From 19.34.6 */ | |
45 #include "systime.h" | 47 #include "systime.h" |
46 #include "syswait.h" | 48 #include "syswait.h" |
47 #include "process.h" | 49 #include "process.h" |
50 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */ | |
48 | 51 |
49 /* Control whether spawnve quotes arguments as necessary to ensure | 52 /* Control whether spawnve quotes arguments as necessary to ensure |
50 correct parsing by child process. Because not all uses of spawnve | 53 correct parsing by child process. Because not all uses of spawnve |
51 are careful about constructing argv arrays, we make this behaviour | 54 are careful about constructing argv arrays, we make this behaviour |
52 conditional (off by default). */ | 55 conditional (off by default). */ |
53 Lisp_Object Vwin32_quote_process_args; | 56 Lisp_Object Vwin32_quote_process_args; |
54 | 57 |
58 /* Control whether create_child causes the process' window to be | |
59 hidden. The default is nil. */ | |
60 Lisp_Object Vwin32_start_process_show_window; | |
61 | |
62 /* Control whether create_child causes the process to inherit Emacs' | |
63 console window, or be given a new one of its own. The default is | |
64 nil, to allow multiple DOS programs to run on Win95. Having separate | |
65 consoles also allows Emacs to cleanly terminate process groups. */ | |
66 Lisp_Object Vwin32_start_process_share_console; | |
67 | |
55 /* Time to sleep before reading from a subprocess output pipe - this | 68 /* Time to sleep before reading from a subprocess output pipe - this |
56 avoids the inefficiency of frequently reading small amounts of data. | 69 avoids the inefficiency of frequently reading small amounts of data. |
57 This is primarily necessary for handling DOS processes on Windows 95, | 70 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. */ | 71 but is useful for Win32 processes on both Win95 and NT as well. */ |
59 Lisp_Object Vwin32_pipe_read_delay; | 72 Lisp_Object Vwin32_pipe_read_delay; |
60 | 73 |
61 /* Control conversion of upper case file names to lower case. | 74 /* Control conversion of upper case file names to lower case. |
62 nil means no, t means yes. */ | 75 nil means no, t means yes. */ |
63 Lisp_Object Vwin32_downcase_file_names; | 76 Lisp_Object Vwin32_downcase_file_names; |
64 | 77 |
65 /* Keep track of whether we have already started a DOS program. */ | 78 /* Control whether stat() attempts to generate fake but hopefully |
66 BOOL dos_process_running; | 79 "accurate" inode values, by hashing the absolute truenames of files. |
80 This should detect aliasing between long and short names, but still | |
81 allows the possibility of hash collisions. */ | |
82 Lisp_Object Vwin32_generate_fake_inodes; | |
83 | |
84 /* Control whether stat() attempts to determine file type and link count | |
85 exactly, at the expense of slower operation. Since true hard links | |
86 are supported on NTFS volumes, this is only relevant on NT. */ | |
87 Lisp_Object Vwin32_get_true_file_attributes; | |
88 | |
89 Lisp_Object Qhigh, Qlow; | |
67 | 90 |
68 #ifndef SYS_SIGLIST_DECLARED | 91 #ifndef SYS_SIGLIST_DECLARED |
69 extern char *sys_siglist[]; | 92 extern char *sys_siglist[]; |
70 #endif | 93 #endif |
71 | 94 |
269 } | 292 } |
270 } | 293 } |
271 return 0; | 294 return 0; |
272 } | 295 } |
273 | 296 |
297 /* To avoid Emacs changing directory, we just record here the directory | |
298 the new process should start in. This is set just before calling | |
299 sys_spawnve, and is not generally valid at any other time. */ | |
300 static char * process_dir; | |
301 | |
274 static BOOL | 302 static BOOL |
275 create_child (char *exe, char *cmdline, char *env, | 303 create_child (char *exe, char *cmdline, char *env, |
276 int * pPid, child_process *cp) | 304 int * pPid, child_process *cp) |
277 { | 305 { |
278 STARTUPINFO start; | 306 STARTUPINFO start; |
279 SECURITY_ATTRIBUTES sec_attrs; | 307 SECURITY_ATTRIBUTES sec_attrs; |
280 SECURITY_DESCRIPTOR sec_desc; | 308 SECURITY_DESCRIPTOR sec_desc; |
309 char dir[ MAXPATHLEN ]; | |
281 | 310 |
282 if (cp == NULL) abort (); | 311 if (cp == NULL) abort (); |
283 | 312 |
284 memset (&start, 0, sizeof (start)); | 313 memset (&start, 0, sizeof (start)); |
285 start.cb = sizeof (start); | 314 start.cb = sizeof (start); |
286 | 315 |
287 #ifdef HAVE_NTGUI | 316 #ifdef HAVE_NTGUI |
317 if (NILP (Vwin32_start_process_show_window)) | |
288 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | 318 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; |
319 else | |
320 start.dwFlags = STARTF_USESTDHANDLES; | |
289 start.wShowWindow = SW_HIDE; | 321 start.wShowWindow = SW_HIDE; |
290 | 322 |
291 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE); | 323 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE); |
292 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); | 324 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); |
293 start.hStdError = GetStdHandle (STD_ERROR_HANDLE); | 325 start.hStdError = GetStdHandle (STD_ERROR_HANDLE); |
300 goto EH_Fail; | 332 goto EH_Fail; |
301 sec_attrs.nLength = sizeof (sec_attrs); | 333 sec_attrs.nLength = sizeof (sec_attrs); |
302 sec_attrs.lpSecurityDescriptor = &sec_desc; | 334 sec_attrs.lpSecurityDescriptor = &sec_desc; |
303 sec_attrs.bInheritHandle = FALSE; | 335 sec_attrs.bInheritHandle = FALSE; |
304 | 336 |
337 strcpy (dir, process_dir); | |
338 unixtodos_filename (dir); | |
339 | |
305 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, | 340 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, |
306 CREATE_NEW_PROCESS_GROUP, | 341 (!NILP (Vwin32_start_process_share_console) |
307 env, NULL, | 342 ? CREATE_NEW_PROCESS_GROUP |
343 : CREATE_NEW_CONSOLE), | |
344 env, dir, | |
308 &start, &cp->procinfo)) | 345 &start, &cp->procinfo)) |
309 goto EH_Fail; | 346 goto EH_Fail; |
310 | 347 |
311 cp->pid = (int) cp->procinfo.dwProcessId; | 348 cp->pid = (int) cp->procinfo.dwProcessId; |
312 | 349 |
314 if (cp->pid < 0) | 351 if (cp->pid < 0) |
315 cp->pid = -cp->pid; | 352 cp->pid = -cp->pid; |
316 | 353 |
317 /* pid must fit in a Lisp_Int */ | 354 /* pid must fit in a Lisp_Int */ |
318 cp->pid = (cp->pid & VALMASK); | 355 cp->pid = (cp->pid & VALMASK); |
319 | |
320 | 356 |
321 *pPid = cp->pid; | 357 *pPid = cp->pid; |
322 | 358 |
323 return TRUE; | 359 return TRUE; |
324 | 360 |
379 "with %lu for fd %ld\n", GetLastError (), cp->fd)); | 415 "with %lu for fd %ld\n", GetLastError (), cp->fd)); |
380 CloseHandle (cp->procinfo.hProcess); | 416 CloseHandle (cp->procinfo.hProcess); |
381 cp->procinfo.hProcess = NULL; | 417 cp->procinfo.hProcess = NULL; |
382 CloseHandle (cp->procinfo.hThread); | 418 CloseHandle (cp->procinfo.hThread); |
383 cp->procinfo.hThread = NULL; | 419 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 } | 420 } |
390 | 421 |
391 /* For asynchronous children, the child_proc resources will be freed | 422 /* For asynchronous children, the child_proc resources will be freed |
392 when the last pipe read descriptor is closed; for synchronous | 423 when the last pipe read descriptor is closed; for synchronous |
393 children, we must explicitly free the resources now because | 424 children, we must explicitly free the resources now because |
415 /* We want to wait for a specific child */ | 446 /* We want to wait for a specific child */ |
416 wait_hnd[nh] = dead_child->procinfo.hProcess; | 447 wait_hnd[nh] = dead_child->procinfo.hProcess; |
417 cps[nh] = dead_child; | 448 cps[nh] = dead_child; |
418 if (!wait_hnd[nh]) abort (); | 449 if (!wait_hnd[nh]) abort (); |
419 nh++; | 450 nh++; |
451 active = 0; | |
452 goto get_result; | |
420 } | 453 } |
421 else | 454 else |
422 { | 455 { |
423 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | 456 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) |
424 /* some child_procs might be sockets; ignore them */ | 457 /* some child_procs might be sockets; ignore them */ |
425 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess) | 458 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess) |
426 { | 459 { |
427 wait_hnd[nh] = cp->procinfo.hProcess; | 460 wait_hnd[nh] = cp->procinfo.hProcess; |
428 cps[nh] = cp; | 461 cps[nh] = cp; |
429 if (!wait_hnd[nh]) abort (); | 462 if (!wait_hnd[nh]) abort (); /* Sync with FSF Emacs 19.34.6 note: only in XEmacs */ |
430 nh++; | 463 nh++; |
431 } | 464 } |
432 } | 465 } |
433 | 466 |
434 if (nh == 0) | 467 if (nh == 0) |
436 /* Nothing to wait on, so fail */ | 469 /* Nothing to wait on, so fail */ |
437 errno = ECHILD; | 470 errno = ECHILD; |
438 return -1; | 471 return -1; |
439 } | 472 } |
440 | 473 |
441 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, INFINITE); | 474 do |
475 { | |
476 /* Check for quit about once a second. */ | |
477 QUIT; | |
478 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000); | |
479 } while (active == WAIT_TIMEOUT); | |
480 | |
442 if (active == WAIT_FAILED) | 481 if (active == WAIT_FAILED) |
443 { | 482 { |
444 errno = EBADF; | 483 errno = EBADF; |
445 return -1; | 484 return -1; |
446 } | 485 } |
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 && | 486 else if (active >= WAIT_OBJECT_0 && |
454 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) | 487 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) |
455 { | 488 { |
456 active -= WAIT_OBJECT_0; | 489 active -= WAIT_OBJECT_0; |
457 } | 490 } |
458 else if (active >= WAIT_ABANDONED_0 && | 491 else if (active >= WAIT_ABANDONED_0 && |
459 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | 492 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) |
460 { | 493 { |
461 active -= WAIT_ABANDONED_0; | 494 active -= WAIT_ABANDONED_0; |
462 } | 495 } |
463 | 496 else |
497 abort (); | |
498 | |
499 get_result: | |
464 if (!GetExitCodeProcess (wait_hnd[active], &retval)) | 500 if (!GetExitCodeProcess (wait_hnd[active], &retval)) |
465 { | 501 { |
466 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n", | 502 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n", |
467 GetLastError ())); | 503 GetLastError ())); |
468 retval = 1; | 504 retval = 1; |
518 } | 554 } |
519 | 555 |
520 reap_subprocess (cp); | 556 reap_subprocess (cp); |
521 } | 557 } |
522 | 558 |
559 reap_subprocess (cp); | |
560 | |
523 return pid; | 561 return pid; |
524 } | 562 } |
525 | 563 |
526 int | 564 void |
527 win32_is_dos_binary (char * filename) | 565 win32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app) |
528 { | 566 { |
529 IMAGE_DOS_HEADER dos_header; | 567 file_data executable; |
530 DWORD signature; | 568 char * p; |
531 int fd; | 569 |
532 int is_dos_binary = FALSE; | 570 /* Default values in case we can't tell for sure. */ |
533 | 571 *is_dos_app = FALSE; |
534 fd = open (filename, O_RDONLY | O_BINARY, 0); | 572 *is_cygnus_app = FALSE; |
535 if (fd >= 0) | 573 |
536 { | 574 if (!open_input_file (&executable, filename)) |
537 char * p = strrchr (filename, '.'); | 575 return; |
576 | |
577 p = strrchr (filename, '.'); | |
538 | 578 |
539 /* We can only identify DOS .com programs from the extension. */ | 579 /* We can only identify DOS .com programs from the extension. */ |
540 if (p && stricmp (p, ".com") == 0) | 580 if (p && stricmp (p, ".com") == 0) |
541 is_dos_binary = TRUE; | 581 *is_dos_app = TRUE; |
542 else if (p && stricmp (p, ".bat") == 0) | 582 else if (p && (stricmp (p, ".bat") == 0 || |
543 { | 583 stricmp (p, ".cmd") == 0)) |
544 /* A DOS shell script - it appears that CreateProcess is happy | 584 { |
545 to accept this (somewhat surprisingly); presumably it looks | 585 /* A DOS shell script - it appears that CreateProcess is happy to |
546 at COMSPEC to determine what executable to actually invoke. | 586 accept this (somewhat surprisingly); presumably it looks at |
587 COMSPEC to determine what executable to actually invoke. | |
547 Therefore, we have to do the same here as well. */ | 588 Therefore, we have to do the same here as well. */ |
548 p = getenv ("COMSPEC"); | 589 /* Actually, I think it uses the program association for that |
590 extension, which is defined in the registry. */ | |
591 p = egetenv ("COMSPEC"); | |
549 if (p) | 592 if (p) |
550 is_dos_binary = win32_is_dos_binary (p); | 593 win32_executable_type (p, is_dos_app, is_cygnus_app); |
551 } | 594 } |
552 else | 595 else |
553 { | 596 { |
554 /* Look for DOS .exe signature - if found, we must also check | 597 /* Look for DOS .exe signature - if found, we must also check that |
555 that it isn't really a 16- or 32-bit Windows exe, since | 598 it isn't really a 16- or 32-bit Windows exe, since both formats |
556 both formats start with a DOS program stub. Note that | 599 start with a DOS program stub. Note that 16-bit Windows |
557 16-bit Windows executables use the OS/2 1.x format. */ | 600 executables use the OS/2 1.x format. */ |
558 if (read (fd, &dos_header, sizeof (dos_header)) == sizeof (dos_header) | 601 |
559 && dos_header.e_magic == IMAGE_DOS_SIGNATURE | 602 IMAGE_DOS_HEADER * dos_header; |
560 && lseek (fd, dos_header.e_lfanew, SEEK_SET) != -1) | 603 IMAGE_NT_HEADERS * nt_header; |
604 | |
605 dos_header = (PIMAGE_DOS_HEADER) executable.file_base; | |
606 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
607 goto unwind; | |
608 | |
609 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew); | |
610 | |
611 if ((char *) nt_header > (char *) dos_header + executable.size) | |
612 { | |
613 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
614 *is_dos_app = TRUE; | |
615 } | |
616 else if (nt_header->Signature != IMAGE_NT_SIGNATURE && | |
617 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | |
618 { | |
619 *is_dos_app = TRUE; | |
620 } | |
621 else if (nt_header->Signature == IMAGE_NT_SIGNATURE) | |
622 { | |
623 /* Look for cygwin.dll in DLL import list. */ | |
624 IMAGE_DATA_DIRECTORY import_dir = | |
625 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; | |
626 IMAGE_IMPORT_DESCRIPTOR * imports; | |
627 IMAGE_SECTION_HEADER * section; | |
628 | |
629 section = rva_to_section (import_dir.VirtualAddress, nt_header); | |
630 imports = RVA_TO_PTR (import_dir.VirtualAddress, section, executable); | |
631 | |
632 for ( ; imports->Name; imports++) | |
561 { | 633 { |
562 if (read (fd, &signature, sizeof (signature)) != sizeof (signature) | 634 char * dllname = RVA_TO_PTR (imports->Name, section, executable); |
563 || (signature != IMAGE_NT_SIGNATURE && | 635 |
564 LOWORD (signature) != IMAGE_OS2_SIGNATURE)) | 636 if (strcmp (dllname, "cygwin.dll") == 0) |
565 is_dos_binary = TRUE; | 637 { |
638 *is_cygnus_app = TRUE; | |
639 break; | |
640 } | |
566 } | 641 } |
567 } | 642 } |
568 close (fd); | 643 } |
569 } | 644 |
570 | 645 unwind: |
571 return is_dos_binary; | 646 close_file_data (&executable); |
572 } | 647 } |
573 | 648 |
574 /* We pass our process ID to our children by setting up an environment | 649 int |
575 variable in their environment. */ | 650 compare_env (const char **strp1, const char **strp2) |
576 char ppid_env_var_buffer[64]; | 651 { |
652 const char *str1 = *strp1, *str2 = *strp2; | |
653 | |
654 while (*str1 && *str2 && *str1 != '=' && *str2 != '=') | |
655 { | |
656 if ((*str1) > (*str2)) | |
657 return 1; | |
658 else if ((*str1) < (*str2)) | |
659 return -1; | |
660 str1++, str2++; | |
661 } | |
662 | |
663 if (*str1 == '=' && *str2 == '=') | |
664 return 0; | |
665 else if (*str1 == '=') | |
666 return -1; | |
667 else | |
668 return 1; | |
669 } | |
670 | |
671 void | |
672 merge_and_sort_env (char **envp1, char **envp2, char **new_envp) | |
673 { | |
674 char **optr, **nptr; | |
675 int num; | |
676 | |
677 nptr = new_envp; | |
678 optr = envp1; | |
679 while (*optr) | |
680 *nptr++ = *optr++; | |
681 num = optr - envp1; | |
682 | |
683 optr = envp2; | |
684 while (*optr) | |
685 *nptr++ = *optr++; | |
686 num += optr - envp2; | |
687 | |
688 qsort (new_envp, num, sizeof (char *), compare_env); | |
689 | |
690 *nptr = NULL; | |
691 } | |
577 | 692 |
578 /* When a new child process is created we need to register it in our list, | 693 /* When a new child process is created we need to register it in our list, |
579 so intercept spawn requests. */ | 694 so intercept spawn requests. */ |
580 int | 695 int |
581 sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | 696 sys_spawnve (int mode, char *cmdname, char **argv, char **envp) |
582 { | 697 { |
583 Lisp_Object program, full; | 698 Lisp_Object program, full; |
584 char *cmdline, *env, *parg, **targ; | 699 char *cmdline, *env, *parg, **targ; |
585 int arglen; | 700 int arglen, numenv; |
586 int pid; | 701 int pid; |
587 child_process *cp; | 702 child_process *cp; |
588 int is_dos_binary; | 703 int is_dos_app, is_cygnus_app; |
704 int do_quoting = 0; | |
705 char escape_char; | |
706 /* We pass our process ID to our children by setting up an environment | |
707 variable in their environment. */ | |
708 char ppid_env_var_buffer[64]; | |
709 char *extra_env[] = {ppid_env_var_buffer, NULL}; | |
589 struct gcpro gcpro1; | 710 struct gcpro gcpro1; |
590 | 711 |
591 /* We don't care about the other modes */ | 712 /* We don't care about the other modes */ |
592 if (mode != _P_NOWAIT) | 713 if (mode != _P_NOWAIT) |
593 { | 714 { |
606 { | 727 { |
607 UNGCPRO; | 728 UNGCPRO; |
608 errno = EINVAL; | 729 errno = EINVAL; |
609 return -1; | 730 return -1; |
610 } | 731 } |
611 cmdname = XSTRING (full)->_data; | 732 cmdname = XSTRING_DATA (full); |
612 argv[0] = cmdname; | 733 argv[0] = cmdname; |
613 } | 734 } |
614 UNGCPRO; | 735 UNGCPRO; |
615 | 736 |
616 | 737 /* make sure argv[0] and cmdname are both in DOS format */ |
617 /* make sure cmdname is in DOS format */ | |
618 strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); | 738 strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); |
619 unixtodos_filename (cmdname); | 739 unixtodos_filename (cmdname); |
620 argv[0] = cmdname; | 740 argv[0] = cmdname; |
621 | 741 |
622 /* Check if program is a DOS executable, and if so whether we are | 742 /* Determine whether program is a 16-bit DOS executable, or a Win32 |
623 allowed to start it. */ | 743 executable that is implicitly linked to the Cygnus dll (implying it |
624 is_dos_binary = win32_is_dos_binary (cmdname); | 744 was compiled with the Cygnus GNU toolchain and hence relies on |
625 if (is_dos_binary && dos_process_running) | 745 cygwin.dll to parse the command line - we use this to decide how to |
626 { | 746 escape quote chars in command line args that must be quoted). */ |
627 errno = EAGAIN; | 747 win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app); |
628 return -1; | 748 |
749 /* On Windows 95, if cmdname is a DOS app, we invoke a helper | |
750 application to start it by specifying the helper app as cmdname, | |
751 while leaving the real app name as argv[0]. */ | |
752 if (is_dos_app) | |
753 { | |
754 cmdname = alloca (MAXPATHLEN); | |
755 if (egetenv ("CMDPROXY")) | |
756 strcpy (cmdname, egetenv ("CMDPROXY")); | |
757 else | |
758 { | |
759 strcpy (cmdname, XSTRING_DATA (Vinvocation_directory)); | |
760 strcat (cmdname, "cmdproxy.exe"); | |
761 } | |
762 unixtodos_filename (cmdname); | |
629 } | 763 } |
630 | 764 |
631 /* we have to do some conjuring here to put argv and envp into the | 765 /* we have to do some conjuring here to put argv and envp into the |
632 form CreateProcess wants... argv needs to be a space separated/null | 766 form CreateProcess wants... argv needs to be a space separated/null |
633 terminated list of parameters, and envp is a null | 767 terminated list of parameters, and envp is a null |
634 separated/double-null terminated list of parameters. | 768 separated/double-null terminated list of parameters. |
635 | 769 |
636 Additionally, zero-length args and args containing whitespace need | 770 Additionally, zero-length args and args containing whitespace or |
637 to be wrapped in double quotes. Args containing embedded double | 771 quote chars need to be wrapped in double quotes - for this to work, |
638 quotes (as opposed to enclosing quotes, which we leave alone) are | 772 embedded quotes need to be escaped as well. The aim is to ensure |
639 usually illegal (most Win32 programs do not implement escaping of | 773 the child process reconstructs the argv array we start with |
640 double quotes - sad but true, at least for programs compiled with | 774 exactly, so we treat quotes at the beginning and end of arguments |
641 MSVC), but we will escape quotes anyway for those programs that can | 775 as embedded quotes. |
642 handle it. The Win32 gcc library from Cygnus doubles quotes to | 776 |
643 escape them, so we will use that convention. | 777 The Win32 GNU-based library from Cygnus doubles quotes to escape |
778 them, while MSVC uses backslash for escaping. (Actually the MSVC | |
779 startup code does attempt to recognise doubled quotes and accept | |
780 them, but gets it wrong and ends up requiring three quotes to get a | |
781 single embedded quote!) So by default we decide whether to use | |
782 quote or backslash as the escape character based on whether the | |
783 binary is apparently a Cygnus compiled app. | |
784 | |
785 Note that using backslash to escape embedded quotes requires | |
786 additional special handling if an embedded quote is already | |
787 preceeded by backslash, or if an arg requiring quoting ends with | |
788 backslash. In such cases, the run of escape characters needs to be | |
789 doubled. For consistency, we apply this special handling as long | |
790 as the escape character is not quote. | |
644 | 791 |
645 Since I have no idea how large argv and envp are likely to be | 792 Since we have no idea how large argv and envp are likely to be we |
646 we figure out list lengths on the fly and allocate them. */ | 793 figure out list lengths on the fly and allocate them. */ |
794 | |
795 if (!NILP (Vwin32_quote_process_args)) | |
796 { | |
797 do_quoting = 1; | |
798 /* Override escape char by binding win32-quote-process-args to | |
799 desired character, or use t for auto-selection. */ | |
800 if (INTP (Vwin32_quote_process_args)) | |
801 escape_char = XINT (Vwin32_quote_process_args); | |
802 else | |
803 escape_char = is_cygnus_app ? '"' : '\\'; | |
804 } | |
647 | 805 |
648 /* do argv... */ | 806 /* do argv... */ |
649 arglen = 0; | 807 arglen = 0; |
650 targ = argv; | 808 targ = argv; |
651 while (*targ) | 809 while (*targ) |
652 { | 810 { |
653 char * p = *targ; | 811 char * p = *targ; |
654 int add_quotes = 0; | 812 int need_quotes = 0; |
813 int escape_char_run = 0; | |
655 | 814 |
656 if (*p == 0) | 815 if (*p == 0) |
657 add_quotes = 1; | 816 need_quotes = 1; |
658 while (*p) | 817 for ( ; *p; p++) |
659 if (*p++ == '"') | 818 { |
819 if (*p == '"') | |
660 { | 820 { |
661 /* allow for embedded quotes to be doubled - we won't | 821 /* allow for embedded quotes to be escaped */ |
662 actually double quotes that aren't embedded though */ | |
663 arglen++; | 822 arglen++; |
664 add_quotes = 1; | 823 need_quotes = 1; |
824 /* handle the case where the embedded quote is already escaped */ | |
825 if (escape_char_run > 0) | |
826 { | |
827 /* To preserve the arg exactly, we need to double the | |
828 preceding escape characters (plus adding one to | |
829 escape the quote character itself). */ | |
830 arglen += escape_char_run; | |
665 } | 831 } |
832 } | |
666 else if (*p == ' ' || *p == '\t') | 833 else if (*p == ' ' || *p == '\t') |
667 add_quotes = 1; | 834 { |
668 if (add_quotes) | 835 need_quotes = 1; |
836 } | |
837 | |
838 if (*p == escape_char && escape_char != '"') | |
839 escape_char_run++; | |
840 else | |
841 escape_char_run = 0; | |
842 } | |
843 if (need_quotes) | |
844 { | |
669 arglen += 2; | 845 arglen += 2; |
846 /* handle the case where the arg ends with an escape char - we | |
847 must not let the enclosing quote be escaped. */ | |
848 if (escape_char_run > 0) | |
849 arglen += escape_char_run; | |
850 } | |
670 arglen += strlen (*targ++) + 1; | 851 arglen += strlen (*targ++) + 1; |
671 } | 852 } |
672 cmdline = alloca (arglen); | 853 cmdline = alloca (arglen); |
673 targ = argv; | 854 targ = argv; |
674 parg = cmdline; | 855 parg = cmdline; |
675 while (*targ) | 856 while (*targ) |
676 { | 857 { |
677 char * p = *targ; | 858 char * p = *targ; |
678 int add_quotes = 0; | 859 int need_quotes = 0; |
679 | 860 |
680 if (*p == 0) | 861 if (*p == 0) |
681 add_quotes = 1; | 862 need_quotes = 1; |
682 | 863 |
683 if (!NILP (Vwin32_quote_process_args)) | 864 if (do_quoting) |
684 { | 865 { |
685 /* This is conditional because it sometimes causes more | |
686 problems than it solves, since argv arrays are not always | |
687 carefully constructed. M-x grep, for instance, passes the | |
688 whole command line as one argument, so it becomes | |
689 impossible to pass a regexp which contains spaces. */ | |
690 for ( ; *p; p++) | 866 for ( ; *p; p++) |
691 if (*p == ' ' || *p == '\t' || *p == '"') | 867 if (*p == ' ' || *p == '\t' || *p == '"') |
692 add_quotes = 1; | 868 need_quotes = 1; |
693 } | 869 } |
694 if (add_quotes) | 870 if (need_quotes) |
695 { | 871 { |
872 int escape_char_run = 0; | |
696 char * first; | 873 char * first; |
697 char * last; | 874 char * last; |
698 | 875 |
699 p = *targ; | 876 p = *targ; |
700 first = p; | 877 first = p; |
701 last = p + strlen (p) - 1; | 878 last = p + strlen (p) - 1; |
702 *parg++ = '"'; | 879 *parg++ = '"'; |
880 #if 0 | |
881 /* This version does not escape quotes if they occur at the | |
882 beginning or end of the arg - this could lead to incorrect | |
883 behaviour when the arg itself represents a command line | |
884 containing quoted args. I believe this was originally done | |
885 as a hack to make some things work, before | |
886 `win32-quote-process-args' was added. */ | |
703 while (*p) | 887 while (*p) |
704 { | 888 { |
705 if (*p == '"' && p > first && p < last) | 889 if (*p == '"' && p > first && p < last) |
706 *parg++ = '"'; /* double up embedded quotes only */ | 890 *parg++ = escape_char; /* escape embedded quotes */ |
707 *parg++ = *p++; | 891 *parg++ = *p++; |
708 } | 892 } |
893 #else | |
894 for ( ; *p; p++) | |
895 { | |
896 if (*p == '"') | |
897 { | |
898 /* double preceding escape chars if any */ | |
899 while (escape_char_run > 0) | |
900 { | |
901 *parg++ = escape_char; | |
902 escape_char_run--; | |
903 } | |
904 /* escape all quote chars, even at beginning or end */ | |
905 *parg++ = escape_char; | |
906 } | |
907 *parg++ = *p; | |
908 | |
909 if (*p == escape_char && escape_char != '"') | |
910 escape_char_run++; | |
911 else | |
912 escape_char_run = 0; | |
913 } | |
914 /* double escape chars before enclosing quote */ | |
915 while (escape_char_run > 0) | |
916 { | |
917 *parg++ = escape_char; | |
918 escape_char_run--; | |
919 } | |
920 #endif | |
709 *parg++ = '"'; | 921 *parg++ = '"'; |
710 } | 922 } |
711 else | 923 else |
712 { | 924 { |
713 strcpy (parg, *targ); | 925 strcpy (parg, *targ); |
719 *--parg = '\0'; | 931 *--parg = '\0'; |
720 | 932 |
721 /* and envp... */ | 933 /* and envp... */ |
722 arglen = 1; | 934 arglen = 1; |
723 targ = envp; | 935 targ = envp; |
936 numenv = 1; /* for end null */ | |
724 while (*targ) | 937 while (*targ) |
725 { | 938 { |
726 arglen += strlen (*targ++) + 1; | 939 arglen += strlen (*targ++) + 1; |
727 } | 940 numenv++; |
941 } | |
942 /* extra env vars... */ | |
728 sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d", | 943 sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d", |
729 GetCurrentProcessId ()); | 944 GetCurrentProcessId ()); |
730 arglen += strlen (ppid_env_var_buffer) + 1; | 945 arglen += strlen (ppid_env_var_buffer) + 1; |
731 | 946 numenv++; |
947 | |
948 /* merge env passed in and extra env into one, and sort it. */ | |
949 targ = (char **) alloca (numenv * sizeof (char *)); | |
950 merge_and_sort_env (envp, extra_env, targ); | |
951 | |
952 /* concatenate env entries. */ | |
732 env = alloca (arglen); | 953 env = alloca (arglen); |
733 targ = envp; | |
734 parg = env; | 954 parg = env; |
735 while (*targ) | 955 while (*targ) |
736 { | 956 { |
737 strcpy (parg, *targ); | 957 strcpy (parg, *targ); |
738 parg += strlen (*targ++); | 958 parg += strlen (*targ++); |
739 *parg++ = '\0'; | 959 *parg++ = '\0'; |
740 } | 960 } |
741 strcpy (parg, ppid_env_var_buffer); | |
742 parg += strlen (ppid_env_var_buffer); | |
743 *parg++ = '\0'; | 961 *parg++ = '\0'; |
744 *parg = '\0'; | 962 *parg = '\0'; |
745 | 963 |
746 cp = new_child (); | 964 cp = new_child (); |
747 if (cp == NULL) | 965 if (cp == NULL) |
756 delete_child (cp); | 974 delete_child (cp); |
757 errno = ENOEXEC; | 975 errno = ENOEXEC; |
758 return -1; | 976 return -1; |
759 } | 977 } |
760 | 978 |
761 if (is_dos_binary) | |
762 { | |
763 cp->is_dos_process = TRUE; | |
764 dos_process_running = TRUE; | |
765 } | |
766 | |
767 return pid; | 979 return pid; |
768 } | 980 } |
769 | 981 |
770 /* Emulate the select call | 982 /* Emulate the select call |
771 Wait for available input on any of the given rfds, or timeout if | 983 Wait for available input on any of the given rfds, or timeout if |
772 a timeout is given and no input is detected | 984 a timeout is given and no input is detected |
773 wfds and efds are not supported and must be NULL. */ | 985 wfds and efds are not supported and must be NULL. |
774 | 986 |
775 #if 0 | 987 For simplicity, we detect the death of child processes here and |
988 synchronously call the SIGCHLD handler. Since it is possible for | |
989 children to be created without a corresponding pipe handle from which | |
990 to read output, we wait separately on the process handles as well as | |
991 the char_avail events for each process pipe. We only call | |
992 wait/reap_process when the process actually terminates. */ | |
993 | |
776 /* From ntterm.c */ | 994 /* From ntterm.c */ |
777 extern HANDLE keyboard_handle; | 995 extern HANDLE keyboard_handle; |
778 #endif | |
779 /* From process.c */ | 996 /* From process.c */ |
780 extern int proc_buffered_char[]; | 997 extern int proc_buffered_char[]; |
781 | 998 |
782 int | 999 int |
783 sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, | 1000 sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, |
784 EMACS_TIME *timeout) | 1001 EMACS_TIME *timeout) |
785 { | 1002 { |
786 SELECT_TYPE orfds; | 1003 SELECT_TYPE orfds; |
787 DWORD timeout_ms; | 1004 DWORD timeout_ms, start_time; |
788 int i, nh, nr; | 1005 int i, nh, nc, nr; |
789 DWORD active; | 1006 DWORD active; |
790 child_process *cp; | 1007 child_process *cp, *cps[MAX_CHILDREN]; |
791 HANDLE wait_hnd[MAXDESC]; | 1008 HANDLE wait_hnd[MAXDESC + MAX_CHILDREN]; |
792 int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ | 1009 int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ |
793 | 1010 |
1011 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; | |
1012 | |
794 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ | 1013 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ |
795 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) | 1014 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) |
796 { | 1015 { |
797 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); | 1016 Sleep (timeout_ms); |
798 return 0; | 1017 return 0; |
799 } | 1018 } |
800 | 1019 |
801 /* Otherwise, we only handle rfds, so fail otherwise. */ | 1020 /* Otherwise, we only handle rfds, so fail otherwise. */ |
802 if (rfds == NULL || wfds != NULL || efds != NULL) | 1021 if (rfds == NULL || wfds != NULL || efds != NULL) |
807 | 1026 |
808 orfds = *rfds; | 1027 orfds = *rfds; |
809 FD_ZERO (rfds); | 1028 FD_ZERO (rfds); |
810 nr = 0; | 1029 nr = 0; |
811 | 1030 |
812 /* Build a list of handles to wait on. */ | 1031 /* Build a list of pipe handles to wait on. */ |
813 nh = 0; | 1032 nh = 0; |
814 for (i = 0; i < nfds; i++) | 1033 for (i = 0; i < nfds; i++) |
815 if (FD_ISSET (i, &orfds)) | 1034 if (FD_ISSET (i, &orfds)) |
816 { | 1035 { |
817 if (i == 0) | 1036 if (i == 0) |
818 { | 1037 { |
819 #if 0 | 1038 #if 0 |
1039 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */ | |
820 if (keyboard_handle) | 1040 if (keyboard_handle) |
821 { | 1041 { |
822 /* Handle stdin specially */ | 1042 /* Handle stdin specially */ |
823 wait_hnd[nh] = keyboard_handle; | 1043 wait_hnd[nh] = keyboard_handle; |
824 fdindex[nh] = i; | 1044 fdindex[nh] = i; |
826 } | 1046 } |
827 #endif | 1047 #endif |
828 | 1048 |
829 /* Check for any emacs-generated input in the queue since | 1049 /* Check for any emacs-generated input in the queue since |
830 it won't be detected in the wait */ | 1050 it won't be detected in the wait */ |
831 if (detect_input_pending ()) | 1051 if (detect_input_pending ()) |
832 { | 1052 { |
833 FD_SET (i, rfds); | 1053 FD_SET (i, rfds); |
834 return 1; | 1054 return 1; |
835 } | 1055 } |
836 } | 1056 } |
893 #endif | 1113 #endif |
894 } | 1114 } |
895 else | 1115 else |
896 { | 1116 { |
897 /* Unable to find something to wait on for this fd, skip */ | 1117 /* Unable to find something to wait on for this fd, skip */ |
1118 | |
1119 /* Note that this is not a fatal error, and can in fact | |
1120 happen in unusual circumstances. Specifically, if | |
1121 sys_spawnve fails, eg. because the program doesn't | |
1122 exist, and debug-on-error is t so Fsignal invokes a | |
1123 nested input loop, then the process output pipe is | |
1124 still included in input_wait_mask with no child_proc | |
1125 associated with it. (It is removed when the debugger | |
1126 exits the nested input loop and the error is thrown.) */ | |
1127 | |
898 DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i)); | 1128 DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i)); |
899 abort (); | 1129 } |
900 } | 1130 } |
901 } | 1131 } |
1132 | |
1133 count_children: | |
1134 /* Add handles of child processes. */ | |
1135 nc = 0; | |
1136 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
1137 /* Some child_procs might be sockets; ignore them. Also some | |
1138 children may have died already, but we haven't finished reading | |
1139 the process output; ignore them too. */ | |
1140 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess | |
1141 && (cp->fd < 0 | |
1142 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 | |
1143 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) | |
1144 ) | |
1145 { | |
1146 wait_hnd[nh + nc] = cp->procinfo.hProcess; | |
1147 cps[nc] = cp; | |
1148 nc++; | |
902 } | 1149 } |
903 | 1150 |
904 /* Nothing to look for, so we didn't find anything */ | 1151 /* Nothing to look for, so we didn't find anything */ |
905 if (nh == 0) | 1152 if (nh + nc == 0) |
906 { | 1153 { |
907 if (timeout) | 1154 if (timeout) |
908 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); | 1155 Sleep (timeout_ms); |
909 return 0; | 1156 return 0; |
910 } | 1157 } |
911 | 1158 |
912 /* | 1159 /* Wait for input or child death to be signalled. */ |
913 Wait for input | 1160 start_time = GetTickCount (); |
914 If a child process dies while this is waiting, its pipe will break | 1161 active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms); |
915 so the reader thread will signal an error condition, thus, the wait | |
916 will wake up | |
917 */ | |
918 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; | |
919 | |
920 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); | |
921 | 1162 |
922 if (active == WAIT_FAILED) | 1163 if (active == WAIT_FAILED) |
923 { | 1164 { |
924 DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n", | 1165 DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n", |
925 nh, timeout_ms, GetLastError ())); | 1166 nh + nc, timeout_ms, GetLastError ())); |
926 /* don't return EBADF - this causes wait_reading_process_input to | 1167 /* don't return EBADF - this causes wait_reading_process_input to |
927 abort; WAIT_FAILED is returned when single-stepping under | 1168 abort; WAIT_FAILED is returned when single-stepping under |
928 Windows 95 after switching thread focus in debugger, and | 1169 Windows 95 after switching thread focus in debugger, and |
929 possibly at other times. */ | 1170 possibly at other times. */ |
930 errno = EINTR; | 1171 errno = EINTR; |
942 else if (active >= WAIT_ABANDONED_0 && | 1183 else if (active >= WAIT_ABANDONED_0 && |
943 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | 1184 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) |
944 { | 1185 { |
945 active -= WAIT_ABANDONED_0; | 1186 active -= WAIT_ABANDONED_0; |
946 } | 1187 } |
1188 else | |
1189 abort (); | |
947 | 1190 |
948 /* Loop over all handles after active (now officially documented as | 1191 /* Loop over all handles after active (now officially documented as |
949 being the first signalled handle in the array). We do this to | 1192 being the first signalled handle in the array). We do this to |
950 ensure fairness, so that all channels with data available will be | 1193 ensure fairness, so that all channels with data available will be |
951 processed - otherwise higher numbered channels could be starved. */ | 1194 processed - otherwise higher numbered channels could be starved. */ |
952 do | 1195 do |
953 { | 1196 { |
954 if (fdindex[active] == 0) | 1197 if (active >= nh) |
955 { | 1198 { |
956 /* Keyboard input available */ | 1199 cp = cps[active - nh]; |
957 FD_SET (0, rfds); | 1200 |
958 nr++; | 1201 /* We cannot always signal SIGCHLD immediately; if we have not |
959 } | 1202 finished reading the process output, we must delay sending |
960 else | 1203 SIGCHLD until we do. */ |
961 { | 1204 |
962 /* must be a socket or pipe */ | 1205 if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0) |
963 int current_status; | 1206 fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD; |
964 | 1207 /* SIG_DFL for SIGCHLD is ignore */ |
965 cp = fd_info[ fdindex[active] ].cp; | 1208 else if (sig_handlers[SIGCHLD] != SIG_DFL && |
966 | |
967 /* Read ahead should have completed, either succeeding or failing. */ | |
968 FD_SET (fdindex[active], rfds); | |
969 nr++; | |
970 current_status = cp->status; | |
971 if (current_status != STATUS_READ_SUCCEEDED) | |
972 { | |
973 if (current_status != STATUS_READ_FAILED) | |
974 DebPrint (("internal error: subprocess pipe signalled " | |
975 "at the wrong time (status %d)\n!", current_status)); | |
976 | |
977 /* The child_process entry for a socket or pipe will be | |
978 freed when the last descriptor using it is closed; for | |
979 pipes, we call the SIGCHLD handler. */ | |
980 if (fd_info[ fdindex[active] ].flags & FILE_PIPE) | |
981 { | |
982 /* The SIGCHLD handler will do a Wait so we know it won't | |
983 return until the process is dead | |
984 We force Wait to only wait for this process to avoid it | |
985 picking up other children that happen to be dead but that | |
986 we haven't noticed yet | |
987 SIG_DFL for SIGCHLD is ignore? */ | |
988 if (sig_handlers[SIGCHLD] != SIG_DFL && | |
989 sig_handlers[SIGCHLD] != SIG_IGN) | 1209 sig_handlers[SIGCHLD] != SIG_IGN) |
990 { | 1210 { |
991 #ifdef FULL_DEBUG | 1211 #ifdef FULL_DEBUG |
992 DebPrint (("select calling SIGCHLD handler for pid %d\n", | 1212 DebPrint (("select calling SIGCHLD handler for pid %d\n", |
993 cp->pid)); | 1213 cp->pid)); |
994 #endif | 1214 #endif |
995 dead_child = cp; | 1215 dead_child = cp; |
996 sig_handlers[SIGCHLD] (SIGCHLD); | 1216 sig_handlers[SIGCHLD] (SIGCHLD); |
997 dead_child = NULL; | 1217 dead_child = NULL; |
998 } | 1218 } |
999 | |
1000 /* Clean up the child process entry in the table */ | |
1001 reap_subprocess (cp); | |
1002 } | 1219 } |
1220 else if (fdindex[active] == 0) | |
1221 { | |
1222 /* Keyboard input available */ | |
1223 FD_SET (0, rfds); | |
1224 nr++; | |
1003 } | 1225 } |
1004 } | 1226 else |
1005 | 1227 { |
1006 /* Test for input on remaining channels. */ | 1228 /* must be a socket or pipe - read ahead should have |
1007 while (++active < nh) | 1229 completed, either succeeding or failing. */ |
1230 FD_SET (fdindex[active], rfds); | |
1231 nr++; | |
1232 } | |
1233 | |
1234 /* Even though wait_reading_process_output only reads from at most | |
1235 one channel, we must process all channels here so that we reap | |
1236 all children that have died. */ | |
1237 while (++active < nh + nc) | |
1008 if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0) | 1238 if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0) |
1009 break; | 1239 break; |
1010 } while (active < nh); | 1240 } while (active < nh + nc); |
1241 | |
1242 /* If no input has arrived and timeout hasn't expired, wait again. */ | |
1243 if (nr == 0) | |
1244 { | |
1245 DWORD elapsed = GetTickCount () - start_time; | |
1246 | |
1247 if (timeout_ms > elapsed) /* INFINITE is MAX_UINT */ | |
1248 { | |
1249 if (timeout_ms != INFINITE) | |
1250 timeout_ms -= elapsed; | |
1251 goto count_children; | |
1252 } | |
1253 } | |
1011 | 1254 |
1012 return nr; | 1255 return nr; |
1013 } | 1256 } |
1014 | 1257 |
1015 /* Substitute for certain kill () operations */ | 1258 /* Substitute for certain kill () operations */ |
1259 | |
1260 static BOOL CALLBACK | |
1261 find_child_console (HWND hwnd, child_process * cp) | |
1262 { | |
1263 DWORD thread_id; | |
1264 DWORD process_id; | |
1265 | |
1266 thread_id = GetWindowThreadProcessId (hwnd, &process_id); | |
1267 if (process_id == cp->procinfo.dwProcessId) | |
1268 { | |
1269 char window_class[32]; | |
1270 | |
1271 GetClassName (hwnd, window_class, sizeof (window_class)); | |
1272 if (strcmp (window_class, | |
1273 (os_subtype == OS_WIN95) | |
1274 ? "tty" | |
1275 : "ConsoleWindowClass") == 0) | |
1276 { | |
1277 cp->hwnd = hwnd; | |
1278 return FALSE; | |
1279 } | |
1280 } | |
1281 /* keep looking */ | |
1282 return TRUE; | |
1283 } | |
1284 | |
1016 int | 1285 int |
1017 sys_kill (int pid, int sig) | 1286 sys_kill (int pid, int sig) |
1018 { | 1287 { |
1019 child_process *cp; | 1288 child_process *cp; |
1020 HANDLE proc_hand; | 1289 HANDLE proc_hand; |
1041 } | 1310 } |
1042 else | 1311 else |
1043 { | 1312 { |
1044 proc_hand = cp->procinfo.hProcess; | 1313 proc_hand = cp->procinfo.hProcess; |
1045 pid = cp->procinfo.dwProcessId; | 1314 pid = cp->procinfo.dwProcessId; |
1315 | |
1316 /* Try to locate console window for process. */ | |
1317 EnumWindows (find_child_console, (LPARAM) cp); | |
1046 } | 1318 } |
1047 | 1319 |
1048 if (sig == SIGINT) | 1320 if (sig == SIGINT) |
1049 { | 1321 { |
1322 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) | |
1323 { | |
1324 BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0); | |
1325 BYTE vk_break_code = VK_CANCEL; | |
1326 BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0); | |
1327 HWND foreground_window; | |
1328 | |
1329 if (break_scan_code == 0) | |
1330 { | |
1331 /* Fake Ctrl-C if we can't manage Ctrl-Break. */ | |
1332 vk_break_code = 'C'; | |
1333 break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0); | |
1334 } | |
1335 | |
1336 foreground_window = GetForegroundWindow (); | |
1337 if (foreground_window && SetForegroundWindow (cp->hwnd)) | |
1338 { | |
1339 /* Generate keystrokes as if user had typed Ctrl-Break or Ctrl-C. */ | |
1340 keybd_event (VK_CONTROL, control_scan_code, 0, 0); | |
1341 keybd_event (vk_break_code, break_scan_code, 0, 0); | |
1342 keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0); | |
1343 keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0); | |
1344 | |
1345 /* Sleep for a bit to give time for Emacs frame to respond | |
1346 to focus change events (if Emacs was active app). */ | |
1347 Sleep (10); | |
1348 | |
1349 SetForegroundWindow (foreground_window); | |
1350 } | |
1351 } | |
1050 /* Ctrl-Break is NT equivalent of SIGINT. */ | 1352 /* Ctrl-Break is NT equivalent of SIGINT. */ |
1051 if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid)) | 1353 else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid)) |
1052 { | 1354 { |
1053 DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d " | 1355 DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d " |
1054 "for pid %lu\n", GetLastError (), pid)); | 1356 "for pid %lu\n", GetLastError (), pid)); |
1055 errno = EINVAL; | 1357 errno = EINVAL; |
1056 rc = -1; | 1358 rc = -1; |
1057 } | 1359 } |
1058 } | 1360 } |
1059 else | 1361 else |
1060 { | 1362 { |
1363 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) | |
1364 { | |
1365 #if 1 | |
1366 if (os_subtype == OS_WIN95) | |
1367 { | |
1368 /* | |
1369 Another possibility is to try terminating the VDM out-right by | |
1370 calling the Shell VxD (id 0x17) V86 interface, function #4 | |
1371 "SHELL_Destroy_VM", ie. | |
1372 | |
1373 mov edx,4 | |
1374 mov ebx,vm_handle | |
1375 call shellapi | |
1376 | |
1377 First need to determine the current VM handle, and then arrange for | |
1378 the shellapi call to be made from the system vm (by using | |
1379 Switch_VM_and_callback). | |
1380 | |
1381 Could try to invoke DestroyVM through CallVxD. | |
1382 | |
1383 */ | |
1384 #if 0 | |
1385 /* On Win95, posting WM_QUIT causes the 16-bit subsystem | |
1386 to hang when cmdproxy is used in conjunction with | |
1387 command.com for an interactive shell. Posting | |
1388 WM_CLOSE pops up a dialog that, when Yes is selected, | |
1389 does the same thing. TerminateProcess is also less | |
1390 than ideal in that subprocesses tend to stick around | |
1391 until the machine is shutdown, but at least it | |
1392 doesn't freeze the 16-bit subsystem. */ | |
1393 PostMessage (cp->hwnd, WM_QUIT, 0xff, 0); | |
1394 #endif | |
1395 if (!TerminateProcess (proc_hand, 0xff)) | |
1396 { | |
1397 DebPrint (("sys_kill.TerminateProcess returned %d " | |
1398 "for pid %lu\n", GetLastError (), pid)); | |
1399 errno = EINVAL; | |
1400 rc = -1; | |
1401 } | |
1402 } | |
1403 else | |
1404 #endif | |
1405 PostMessage (cp->hwnd, WM_CLOSE, 0, 0); | |
1406 } | |
1061 /* Kill the process. On Win32 this doesn't kill child processes | 1407 /* Kill the process. On Win32 this doesn't kill child processes |
1062 so it doesn't work very well for shells which is why it's not | 1408 so it doesn't work very well for shells which is why it's not |
1063 used in every case. Also, don't try to terminate DOS processes | 1409 used in every case. */ |
1064 (on Win95), because this will hang Emacs. */ | 1410 else if (!TerminateProcess (proc_hand, 0xff)) |
1065 if (!(cp && cp->is_dos_process) | |
1066 && !TerminateProcess (proc_hand, 0xff)) | |
1067 { | 1411 { |
1068 DebPrint (("sys_kill.TerminateProcess returned %d " | 1412 DebPrint (("sys_kill.TerminateProcess returned %d " |
1069 "for pid %lu\n", GetLastError (), pid)); | 1413 "for pid %lu\n", GetLastError (), pid)); |
1070 errno = EINVAL; | 1414 errno = EINVAL; |
1071 rc = -1; | 1415 rc = -1; |
1077 | 1421 |
1078 return rc; | 1422 return rc; |
1079 } | 1423 } |
1080 | 1424 |
1081 #if 0 | 1425 #if 0 |
1426 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */ | |
1082 extern int report_file_error (CONST char *, Lisp_Object); | 1427 extern int report_file_error (CONST char *, Lisp_Object); |
1083 #endif | 1428 #endif |
1084 /* The following two routines are used to manipulate stdin, stdout, and | 1429 /* The following two routines are used to manipulate stdin, stdout, and |
1085 stderr of our child processes. | 1430 stderr of our child processes. |
1086 | 1431 |
1161 SetStdHandle (STD_INPUT_HANDLE, handles[0]); | 1506 SetStdHandle (STD_INPUT_HANDLE, handles[0]); |
1162 SetStdHandle (STD_OUTPUT_HANDLE, handles[1]); | 1507 SetStdHandle (STD_OUTPUT_HANDLE, handles[1]); |
1163 SetStdHandle (STD_ERROR_HANDLE, handles[2]); | 1508 SetStdHandle (STD_ERROR_HANDLE, handles[2]); |
1164 } | 1509 } |
1165 | 1510 |
1511 void | |
1512 set_process_dir (char * dir) | |
1513 { | |
1514 process_dir = dir; | |
1515 } | |
1516 | |
1166 #ifdef HAVE_SOCKETS | 1517 #ifdef HAVE_SOCKETS |
1167 | 1518 |
1168 /* To avoid problems with winsock implementations that work over dial-up | 1519 /* To avoid problems with winsock implementations that work over dial-up |
1169 connections causing or requiring a connection to exist while Emacs is | 1520 connections causing or requiring a connection to exist while Emacs is |
1170 running, Emacs no longer automatically loads winsock on startup if it | 1521 running, Emacs no longer automatically loads winsock on startup if it |
1230 } | 1581 } |
1231 | 1582 |
1232 #endif /* HAVE_SOCKETS */ | 1583 #endif /* HAVE_SOCKETS */ |
1233 | 1584 |
1234 | 1585 |
1586 /* Some miscellaneous functions that are Windows specific, but not GUI | |
1587 specific (ie. are applicable in terminal or batch mode as well). */ | |
1588 | |
1589 /* lifted from fileio.c */ | |
1590 #define CORRECT_DIR_SEPS(s) \ | |
1591 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \ | |
1592 else unixtodos_filename (s); \ | |
1593 } while (0) | |
1594 | |
1595 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /* | |
1596 Return the short file name version (8.3) of the full path of FILENAME. | |
1597 If FILENAME does not exist, return nil. | |
1598 All path elements in FILENAME are converted to their short names. | |
1599 */ | |
1600 (filename)) | |
1601 { | |
1602 char shortname[MAX_PATH]; | |
1603 | |
1604 CHECK_STRING (filename, 0); | |
1605 | |
1606 /* first expand it. */ | |
1607 filename = Fexpand_file_name (filename, Qnil); | |
1608 | |
1609 /* luckily, this returns the short version of each element in the path. */ | |
1610 if (GetShortPathName (XSTRING_DATA (filename), shortname, MAX_PATH) == 0) | |
1611 return Qnil; | |
1612 | |
1613 CORRECT_DIR_SEPS (shortname); | |
1614 | |
1615 return build_string (shortname); | |
1616 } | |
1617 | |
1618 | |
1619 DEFUN ("win32-long-file-name", Fwin32_long_file_name, 1, 1, "", /* | |
1620 Return the long file name version of the full path of FILENAME. | |
1621 If FILENAME does not exist, return nil. | |
1622 All path elements in FILENAME are converted to their long names. | |
1623 */ | |
1624 (filename)) | |
1625 { | |
1626 char longname[ MAX_PATH ]; | |
1627 | |
1628 CHECK_STRING (filename, 0); | |
1629 | |
1630 /* first expand it. */ | |
1631 filename = Fexpand_file_name (filename, Qnil); | |
1632 | |
1633 if (!win32_get_long_filename (XSTRING_DATA (filename), longname, MAX_PATH)) | |
1634 return Qnil; | |
1635 | |
1636 CORRECT_DIR_SEPS (longname); | |
1637 | |
1638 return build_string (longname); | |
1639 } | |
1640 | |
1641 DEFUN ("win32-set-process-priority", Fwin32_set_process_priority, 2, 2, "", /* | |
1642 Set the priority of PROCESS to PRIORITY. | |
1643 If PROCESS is nil, the priority of Emacs is changed, otherwise the | |
1644 priority of the process whose pid is PROCESS is changed. | |
1645 PRIORITY should be one of the symbols high, normal, or low; | |
1646 any other symbol will be interpreted as normal. | |
1647 | |
1648 If successful, the return value is t, otherwise nil. | |
1649 */ | |
1650 (process, priority)) | |
1651 { | |
1652 HANDLE proc_handle = GetCurrentProcess (); | |
1653 DWORD priority_class = NORMAL_PRIORITY_CLASS; | |
1654 Lisp_Object result = Qnil; | |
1655 | |
1656 CHECK_SYMBOL (priority, 0); | |
1657 | |
1658 if (!NILP (process)) | |
1659 { | |
1660 DWORD pid; | |
1661 child_process *cp; | |
1662 | |
1663 CHECK_INT (process); | |
1664 | |
1665 /* Allow pid to be an internally generated one, or one obtained | |
1666 externally. This is necessary because real pids on Win95 are | |
1667 negative. */ | |
1668 | |
1669 pid = XINT (process); | |
1670 cp = find_child_pid (pid); | |
1671 if (cp != NULL) | |
1672 pid = cp->procinfo.dwProcessId; | |
1673 | |
1674 proc_handle = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid); | |
1675 } | |
1676 | |
1677 if (EQ (priority, Qhigh)) | |
1678 priority_class = HIGH_PRIORITY_CLASS; | |
1679 else if (EQ (priority, Qlow)) | |
1680 priority_class = IDLE_PRIORITY_CLASS; | |
1681 | |
1682 if (proc_handle != NULL) | |
1683 { | |
1684 if (SetPriorityClass (proc_handle, priority_class)) | |
1685 result = Qt; | |
1686 if (!NILP (process)) | |
1687 CloseHandle (proc_handle); | |
1688 } | |
1689 | |
1690 return result; | |
1691 } | |
1692 | |
1693 | |
1694 DEFUN ("win32-get-locale-info", Fwin32_get_locale_info, 1, 2, "", /* | |
1695 "Return information about the Windows locale LCID. | |
1696 By default, return a three letter locale code which encodes the default | |
1697 language as the first two characters, and the country or regionial variant | |
1698 as the third letter. For example, ENU refers to `English (United States)', | |
1699 while ENC means `English (Canadian)'. | |
1700 | |
1701 If the optional argument LONGFORM is non-nil, the long form of the locale | |
1702 name is returned, e.g. `English (United States)' instead. | |
1703 | |
1704 If LCID (a 16-bit number) is not a valid locale, the result is nil. | |
1705 */ | |
1706 (lcid, longform)) | |
1707 { | |
1708 int got_abbrev; | |
1709 int got_full; | |
1710 char abbrev_name[32] = { 0 }; | |
1711 char full_name[256] = { 0 }; | |
1712 | |
1713 CHECK_INT (lcid); | |
1714 | |
1715 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED)) | |
1716 return Qnil; | |
1717 | |
1718 if (NILP (longform)) | |
1719 { | |
1720 got_abbrev = GetLocaleInfo (XINT (lcid), | |
1721 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP, | |
1722 abbrev_name, sizeof (abbrev_name)); | |
1723 if (got_abbrev) | |
1724 return build_string (abbrev_name); | |
1725 } | |
1726 else | |
1727 { | |
1728 got_full = GetLocaleInfo (XINT (lcid), | |
1729 LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP, | |
1730 full_name, sizeof (full_name)); | |
1731 if (got_full) | |
1732 return build_string (full_name); | |
1733 } | |
1734 | |
1735 return Qnil; | |
1736 } | |
1737 | |
1738 | |
1739 DEFUN ("win32-get-current-locale-id", Fwin32_get_current_locale_id, 0, 0, "", /* | |
1740 "Return Windows locale id for current locale setting. | |
1741 This is a numerical value; use `win32-get-locale-info' to convert to a | |
1742 human-readable form. | |
1743 */ | |
1744 ()) | |
1745 { | |
1746 return make_int (GetThreadLocale ()); | |
1747 } | |
1748 | |
1749 | |
1750 DEFUN ("win32-get-default-locale-id", Fwin32_get_default_locale_id, 0, 1, "", /* | |
1751 "Return Windows locale id for default locale setting. | |
1752 By default, the system default locale setting is returned; if the optional | |
1753 parameter USERP is non-nil, the user default locale setting is returned. | |
1754 This is a numerical value; use `win32-get-locale-info' to convert to a | |
1755 human-readable form. | |
1756 */ | |
1757 (userp)) | |
1758 { | |
1759 if (NILP (userp)) | |
1760 return make_int (GetSystemDefaultLCID ()); | |
1761 return make_int (GetUserDefaultLCID ()); | |
1762 } | |
1763 | |
1764 DWORD int_from_hex (char * s) | |
1765 { | |
1766 DWORD val = 0; | |
1767 static char hex[] = "0123456789abcdefABCDEF"; | |
1768 char * p; | |
1769 | |
1770 while (*s && (p = strchr(hex, *s)) != NULL) | |
1771 { | |
1772 unsigned digit = p - hex; | |
1773 if (digit > 15) | |
1774 digit -= 6; | |
1775 val = val * 16 + digit; | |
1776 s++; | |
1777 } | |
1778 return val; | |
1779 } | |
1780 | |
1781 /* We need to build a global list, since the EnumSystemLocale callback | |
1782 function isn't given a context pointer. */ | |
1783 Lisp_Object Vwin32_valid_locale_ids; | |
1784 | |
1785 BOOL CALLBACK enum_locale_fn (LPTSTR localeNum) | |
1786 { | |
1787 DWORD id = int_from_hex (localeNum); | |
1788 Vwin32_valid_locale_ids = Fcons (make_int (id), Vwin32_valid_locale_ids); | |
1789 return TRUE; | |
1790 } | |
1791 | |
1792 DEFUN ("win32-get-valid-locale-ids", Fwin32_get_valid_locale_ids, 0, 0, "", /* | |
1793 Return list of all valid Windows locale ids. | |
1794 Each id is a numerical value; use `win32-get-locale-info' to convert to a | |
1795 human-readable form. | |
1796 */ | |
1797 ()) | |
1798 { | |
1799 Vwin32_valid_locale_ids = Qnil; | |
1800 | |
1801 EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED); | |
1802 | |
1803 Vwin32_valid_locale_ids = Fnreverse (Vwin32_valid_locale_ids); | |
1804 return Vwin32_valid_locale_ids; | |
1805 } | |
1806 | |
1807 | |
1808 DEFUN ("win32-set-current-locale", Fwin32_set_current_locale, 1, 1, "", /* | |
1809 Make Windows locale LCID be the current locale setting for Emacs. | |
1810 If successful, the new locale id is returned, otherwise nil. | |
1811 */ | |
1812 (lcid)) | |
1813 { | |
1814 CHECK_INT (lcid); | |
1815 | |
1816 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED)) | |
1817 return Qnil; | |
1818 | |
1819 if (!SetThreadLocale (XINT (lcid))) | |
1820 return Qnil; | |
1821 | |
1822 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in | |
1823 w32term.h and defined in w32fns.c, both of which are not in current | |
1824 XEmacs. ### Check what we lose by ifdef'ing out these. --marcpa */ | |
1825 #if 0 | |
1826 /* Need to set input thread locale if present. */ | |
1827 if (dwWinThreadId) | |
1828 /* Reply is not needed. */ | |
1829 PostThreadMessage (dwWinThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0); | |
1830 #endif | |
1831 | |
1832 return make_int (GetThreadLocale ()); | |
1833 } | |
1834 | |
1835 | |
1235 syms_of_ntproc () | 1836 syms_of_ntproc () |
1236 { | 1837 { |
1838 Qhigh = intern ("high"); | |
1839 Qlow = intern ("low"); | |
1840 | |
1237 #ifdef HAVE_SOCKETS | 1841 #ifdef HAVE_SOCKETS |
1238 DEFSUBR (Fwin32_has_winsock); | 1842 DEFSUBR (Fwin32_has_winsock); |
1239 DEFSUBR (Fwin32_unload_winsock); | 1843 DEFSUBR (Fwin32_unload_winsock); |
1240 #endif | 1844 #endif |
1845 DEFSUBR (Fwin32_short_file_name); | |
1846 DEFSUBR (Fwin32_long_file_name); | |
1847 DEFSUBR (Fwin32_set_process_priority); | |
1848 DEFSUBR (Fwin32_get_locale_info); | |
1849 DEFSUBR (Fwin32_get_current_locale_id); | |
1850 DEFSUBR (Fwin32_get_default_locale_id); | |
1851 DEFSUBR (Fwin32_get_valid_locale_ids); | |
1852 DEFSUBR (Fwin32_set_current_locale); | |
1241 | 1853 |
1242 DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* | 1854 DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* |
1243 Non-nil enables quoting of process arguments to ensure correct parsing. | 1855 Non-nil enables quoting of process arguments to ensure correct parsing. |
1244 Because Windows does not directly pass argv arrays to child processes, | 1856 Because Windows does not directly pass argv arrays to child processes, |
1245 programs have to reconstruct the argv array by parsing the command | 1857 programs have to reconstruct the argv array by parsing the command |
1246 line string. For an argument to contain a space, it must be enclosed | 1858 line string. For an argument to contain a space, it must be enclosed |
1247 in double quotes or it will be parsed as multiple arguments. | 1859 in double quotes or it will be parsed as multiple arguments. |
1248 | 1860 |
1249 However, the argument list to call-process is not always correctly | 1861 If the value is a character, that character will be used to escape any |
1250 constructed (or arguments have already been quoted), so enabling this | 1862 quote characters that appear, otherwise a suitable escape character |
1251 option may cause unexpected behavior.*/ ); | 1863 will be chosen based on the type of the program. |
1252 Vwin32_quote_process_args = Qnil; | 1864 */ ); |
1865 Vwin32_quote_process_args = Qt; | |
1866 | |
1867 DEFVAR_LISP ("win32-start-process-show-window", | |
1868 &Vwin32_start_process_show_window /* | |
1869 When nil, processes started via start-process hide their windows. | |
1870 When non-nil, they show their window in the method of their choice. | |
1871 */ ); | |
1872 Vwin32_start_process_show_window = Qnil; | |
1873 | |
1874 DEFVAR_LISP ("win32-start-process-share-console", | |
1875 &Vwin32_start_process_share_console /* | |
1876 When nil, processes started via start-process are given a new console. | |
1877 When non-nil, they share the Emacs console; this has the limitation of | |
1878 allowing only only DOS subprocess to run at a time (whether started directly | |
1879 or indirectly by Emacs), and preventing Emacs from cleanly terminating the | |
1880 subprocess group, but may allow Emacs to interrupt a subprocess that doesn't | |
1881 otherwise respond to interrupts from Emacs. | |
1882 */ ); | |
1883 Vwin32_start_process_share_console = Qnil; | |
1253 | 1884 |
1254 DEFVAR_INT ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* | 1885 DEFVAR_INT ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* |
1255 Forced delay before reading subprocess output. | 1886 Forced delay before reading subprocess output. |
1256 This is done to improve the buffering of subprocess output, by | 1887 This is done to improve the buffering of subprocess output, by |
1257 avoiding the inefficiency of frequently reading small amounts of data. | 1888 avoiding the inefficiency of frequently reading small amounts of data. |
1258 | 1889 |
1259 If positive, the value is the number of milliseconds to sleep before | 1890 If positive, the value is the number of milliseconds to sleep before |
1260 reading the subprocess output. If negative, the magnitude is the number | 1891 reading the subprocess output. If negative, the magnitude is the number |
1261 of time slices to wait (effectively boosting the priority of the child | 1892 of time slices to wait (effectively boosting the priority of the child |
1262 process temporarily). A value of zero disables waiting entirely.*/ ); | 1893 process temporarily). A value of zero disables waiting entirely. |
1894 */ ); | |
1263 Vwin32_pipe_read_delay = 50; | 1895 Vwin32_pipe_read_delay = 50; |
1264 | 1896 |
1265 DEFVAR_LISP ("win32-downcase-file-names", &Vwin32_downcase_file_names /* | 1897 DEFVAR_LISP ("win32-downcase-file-names", &Vwin32_downcase_file_names /* |
1266 Non-nil means convert all-upper case file names to lower case. | 1898 Non-nil means convert all-upper case file names to lower case. |
1267 This applies when performing completions and file name expansion.*/ ); | 1899 This applies when performing completions and file name expansion.*/ ); |
1268 Vwin32_downcase_file_names = Qnil; | 1900 Vwin32_downcase_file_names = Qnil; |
1901 | |
1902 #if 0 | |
1903 DEFVAR_LISP ("win32-generate-fake-inodes", &Vwin32_generate_fake_inodes /* | |
1904 "Non-nil means attempt to fake realistic inode values. | |
1905 This works by hashing the truename of files, and should detect | |
1906 aliasing between long and short (8.3 DOS) names, but can have | |
1907 false positives because of hash collisions. Note that determing | |
1908 the truename of a file can be slow. | |
1909 */ ); | |
1910 Vwin32_generate_fake_inodes = Qnil; | |
1911 #endif | |
1912 | |
1913 DEFVAR_LISP ("win32-get-true-file-attributes", &Vwin32_get_true_file_attributes /* | |
1914 "Non-nil means determine accurate link count in file-attributes. | |
1915 This option slows down file-attributes noticeably, so is disabled by | |
1916 default. Note that it is only useful for files on NTFS volumes, | |
1917 where hard links are supported. | |
1918 */ ); | |
1919 Vwin32_get_true_file_attributes = Qnil; | |
1269 } | 1920 } |
1270 /* end of ntproc.c */ | 1921 /* end of ntproc.c */ |