diff options
| author | Karl Heuer | 1996-05-17 21:39:36 +0000 |
|---|---|---|
| committer | Karl Heuer | 1996-05-17 21:39:36 +0000 |
| commit | 817abdf65c757246c49a90bc58e065acd0b7196c (patch) | |
| tree | c8d0e930f0facd268ab0be896659ab4ebec5bfe7 /src | |
| parent | 1f96acec5ef797ba92a93671b97a1760b3c56967 (diff) | |
| download | emacs-817abdf65c757246c49a90bc58e065acd0b7196c.tar.gz emacs-817abdf65c757246c49a90bc58e065acd0b7196c.zip | |
(Vwin32_pipe_read_delay): New var.
(can_run_dos_process, dos_process_running): New vars.
(win32_is_dos_binary): New function.
(reap_subprocess, sys_spawnve): Use them.
(syms_of_ntproc): Defvar and initialize Vwin32_pipe_read_delay.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32proc.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/w32proc.c b/src/w32proc.c index 42b5b6729f8..d537bd5d3a2 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -51,6 +51,17 @@ Boston, MA 02111-1307, USA. | |||
| 51 | conditional (off by default). */ | 51 | conditional (off by default). */ |
| 52 | Lisp_Object Vwin32_quote_process_args; | 52 | Lisp_Object Vwin32_quote_process_args; |
| 53 | 53 | ||
| 54 | /* Time to sleep before reading from a subprocess output pipe - this | ||
| 55 | avoids the inefficiency of frequently reading small amounts of data. | ||
| 56 | This is primarily necessary for handling DOS processes on Windows 95, | ||
| 57 | but is useful for Win32 processes on both Win95 and NT as well. */ | ||
| 58 | Lisp_Object Vwin32_pipe_read_delay; | ||
| 59 | |||
| 60 | /* Keep track of whether we have already started a DOS program, and | ||
| 61 | whether we can run them in the first place. */ | ||
| 62 | BOOL can_run_dos_process; | ||
| 63 | BOOL dos_process_running; | ||
| 64 | |||
| 54 | #ifndef SYS_SIGLIST_DECLARED | 65 | #ifndef SYS_SIGLIST_DECLARED |
| 55 | extern char *sys_siglist[]; | 66 | extern char *sys_siglist[]; |
| 56 | #endif | 67 | #endif |
| @@ -367,6 +378,11 @@ reap_subprocess (child_process *cp) | |||
| 367 | cp->procinfo.hProcess = NULL; | 378 | cp->procinfo.hProcess = NULL; |
| 368 | CloseHandle (cp->procinfo.hThread); | 379 | CloseHandle (cp->procinfo.hThread); |
| 369 | cp->procinfo.hThread = NULL; | 380 | cp->procinfo.hThread = NULL; |
| 381 | |||
| 382 | /* If this was a DOS process, indicate that it is now safe to | ||
| 383 | start a new one. */ | ||
| 384 | if (cp->is_dos_process) | ||
| 385 | dos_process_running = FALSE; | ||
| 370 | } | 386 | } |
| 371 | 387 | ||
| 372 | /* For asynchronous children, the child_proc resources will be freed | 388 | /* For asynchronous children, the child_proc resources will be freed |
| @@ -504,6 +520,54 @@ sys_wait (int *status) | |||
| 504 | return pid; | 520 | return pid; |
| 505 | } | 521 | } |
| 506 | 522 | ||
| 523 | int | ||
| 524 | win32_is_dos_binary (char * filename) | ||
| 525 | { | ||
| 526 | IMAGE_DOS_HEADER dos_header; | ||
| 527 | DWORD signature; | ||
| 528 | int fd; | ||
| 529 | int is_dos_binary = FALSE; | ||
| 530 | |||
| 531 | fd = open (filename, O_RDONLY | O_BINARY, 0); | ||
| 532 | if (fd >= 0) | ||
| 533 | { | ||
| 534 | char * p = strrchr (filename, '.'); | ||
| 535 | |||
| 536 | /* We can only identify DOS .com programs from the extension. */ | ||
| 537 | if (p && stricmp (p, ".com") == 0) | ||
| 538 | is_dos_binary = TRUE; | ||
| 539 | else if (p && stricmp (p, ".bat") == 0) | ||
| 540 | { | ||
| 541 | /* A DOS shell script - it appears that CreateProcess is happy | ||
| 542 | to accept this (somewhat surprisingly); presumably it looks | ||
| 543 | at COMSPEC to determine what executable to actually invoke. | ||
| 544 | Therefore, we have to do the same here as well. */ | ||
| 545 | p = getenv ("COMSPEC"); | ||
| 546 | if (p) | ||
| 547 | is_dos_binary = win32_is_dos_binary (p); | ||
| 548 | } | ||
| 549 | else | ||
| 550 | { | ||
| 551 | /* Look for DOS .exe signature - if found, we must also check | ||
| 552 | that it isn't really a 16- or 32-bit Windows exe, since | ||
| 553 | both formats start with a DOS program stub. Note that | ||
| 554 | 16-bit Windows executables use the OS/2 1.x format. */ | ||
| 555 | if (read (fd, &dos_header, sizeof (dos_header)) == sizeof (dos_header) | ||
| 556 | && dos_header.e_magic == IMAGE_DOS_SIGNATURE | ||
| 557 | && lseek (fd, dos_header.e_lfanew, SEEK_SET) != -1) | ||
| 558 | { | ||
| 559 | if (read (fd, &signature, sizeof (signature)) != sizeof (signature) | ||
| 560 | || (signature != IMAGE_NT_SIGNATURE && | ||
| 561 | LOWORD (signature) != IMAGE_OS2_SIGNATURE)) | ||
| 562 | is_dos_binary = TRUE; | ||
| 563 | } | ||
| 564 | } | ||
| 565 | close (fd); | ||
| 566 | } | ||
| 567 | |||
| 568 | return is_dos_binary; | ||
| 569 | } | ||
| 570 | |||
| 507 | /* We pass our process ID to our children by setting up an environment | 571 | /* We pass our process ID to our children by setting up an environment |
| 508 | variable in their environment. */ | 572 | variable in their environment. */ |
| 509 | char ppid_env_var_buffer[64]; | 573 | char ppid_env_var_buffer[64]; |
| @@ -518,6 +582,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 518 | int arglen; | 582 | int arglen; |
| 519 | int pid; | 583 | int pid; |
| 520 | child_process *cp; | 584 | child_process *cp; |
| 585 | int is_dos_binary; | ||
| 521 | 586 | ||
| 522 | /* We don't care about the other modes */ | 587 | /* We don't care about the other modes */ |
| 523 | if (mode != _P_NOWAIT) | 588 | if (mode != _P_NOWAIT) |
| @@ -549,6 +614,15 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 549 | strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); | 614 | strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); |
| 550 | unixtodos_filename (cmdname); | 615 | unixtodos_filename (cmdname); |
| 551 | argv[0] = cmdname; | 616 | argv[0] = cmdname; |
| 617 | |||
| 618 | /* Check if program is a DOS executable, and if so whether we are | ||
| 619 | allowed to start it. */ | ||
| 620 | is_dos_binary = win32_is_dos_binary (cmdname); | ||
| 621 | if (is_dos_binary && (!can_run_dos_process || dos_process_running)) | ||
| 622 | { | ||
| 623 | errno = (can_run_dos_process) ? EAGAIN : EINVAL; | ||
| 624 | return -1; | ||
| 625 | } | ||
| 552 | 626 | ||
| 553 | /* we have to do some conjuring here to put argv and envp into the | 627 | /* we have to do some conjuring here to put argv and envp into the |
| 554 | form CreateProcess wants... argv needs to be a space separated/null | 628 | form CreateProcess wants... argv needs to be a space separated/null |
| @@ -679,6 +753,12 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 679 | errno = ENOEXEC; | 753 | errno = ENOEXEC; |
| 680 | return -1; | 754 | return -1; |
| 681 | } | 755 | } |
| 756 | |||
| 757 | if (is_dos_binary) | ||
| 758 | { | ||
| 759 | cp->is_dos_process = TRUE; | ||
| 760 | dos_process_running = TRUE; | ||
| 761 | } | ||
| 682 | 762 | ||
| 683 | return pid; | 763 | return pid; |
| 684 | } | 764 | } |
| @@ -1086,5 +1166,16 @@ However, the argument list to call-process is not always correctly\n\ | |||
| 1086 | constructed (or arguments have already been quoted), so enabling this\n\ | 1166 | constructed (or arguments have already been quoted), so enabling this\n\ |
| 1087 | option may cause unexpected behavior."); | 1167 | option may cause unexpected behavior."); |
| 1088 | Vwin32_quote_process_args = Qnil; | 1168 | Vwin32_quote_process_args = Qnil; |
| 1169 | |||
| 1170 | DEFVAR_INT ("win32-pipe-read-delay", &Vwin32_pipe_read_delay, | ||
| 1171 | "Forced delay before reading subprocess output.\n\ | ||
| 1172 | This is done to improve the buffering of subprocess output, by\n\ | ||
| 1173 | avoiding the inefficiency of frequently reading small amounts of data.\n\ | ||
| 1174 | \n\ | ||
| 1175 | If positive, the value is the number of milliseconds to sleep before\n\ | ||
| 1176 | reading the subprocess output. If negative, the magnitude is the number\n\ | ||
| 1177 | of time slices to wait (effectively boosting the priority of the child\n\ | ||
| 1178 | process temporarily). A value of zero disables waiting entirely."); | ||
| 1179 | Vwin32_pipe_read_delay = 50; | ||
| 1089 | } | 1180 | } |
| 1090 | /* end of ntproc.c */ | 1181 | /* end of ntproc.c */ |