Mercurial > emacs
comparison src/w32proc.c @ 49600:23a1cea22d13
Trailing whitespace deleted.
author | Juanma Barranquero <lekktu@gmail.com> |
---|---|
date | Tue, 04 Feb 2003 14:56:31 +0000 |
parents | 514398573221 |
children | 695cf19ef79e d7ddb3e565de |
comparison
equal
deleted
inserted
replaced
49599:5ade352e8d1c | 49600:23a1cea22d13 |
---|---|
118 | 118 |
119 /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ | 119 /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ |
120 static signal_handler sig_handlers[NSIG]; | 120 static signal_handler sig_handlers[NSIG]; |
121 | 121 |
122 /* Fake signal implementation to record the SIGCHLD handler. */ | 122 /* Fake signal implementation to record the SIGCHLD handler. */ |
123 signal_handler | 123 signal_handler |
124 sys_signal (int sig, signal_handler handler) | 124 sys_signal (int sig, signal_handler handler) |
125 { | 125 { |
126 signal_handler old; | 126 signal_handler old; |
127 | 127 |
128 if (sig != SIGCHLD) | 128 if (sig != SIGCHLD) |
129 { | 129 { |
130 errno = EINVAL; | 130 errno = EINVAL; |
131 return SIG_ERR; | 131 return SIG_ERR; |
132 } | 132 } |
149 child_process * | 149 child_process * |
150 new_child (void) | 150 new_child (void) |
151 { | 151 { |
152 child_process *cp; | 152 child_process *cp; |
153 DWORD id; | 153 DWORD id; |
154 | 154 |
155 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | 155 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) |
156 if (!CHILD_ACTIVE (cp)) | 156 if (!CHILD_ACTIVE (cp)) |
157 goto Initialise; | 157 goto Initialise; |
158 if (child_proc_count == MAX_CHILDREN) | 158 if (child_proc_count == MAX_CHILDREN) |
159 return NULL; | 159 return NULL; |
180 } | 180 } |
181 delete_child (cp); | 181 delete_child (cp); |
182 return NULL; | 182 return NULL; |
183 } | 183 } |
184 | 184 |
185 void | 185 void |
186 delete_child (child_process *cp) | 186 delete_child (child_process *cp) |
187 { | 187 { |
188 int i; | 188 int i; |
189 | 189 |
190 /* Should not be deleting a child that is still needed. */ | 190 /* Should not be deleting a child that is still needed. */ |
255 | 255 |
256 /* Thread proc for child process and socket reader threads. Each thread | 256 /* Thread proc for child process and socket reader threads. Each thread |
257 is normally blocked until woken by select() to check for input by | 257 is normally blocked until woken by select() to check for input by |
258 reading one char. When the read completes, char_avail is signalled | 258 reading one char. When the read completes, char_avail is signalled |
259 to wake up the select emulator and the thread blocks itself again. */ | 259 to wake up the select emulator and the thread blocks itself again. */ |
260 DWORD WINAPI | 260 DWORD WINAPI |
261 reader_thread (void *arg) | 261 reader_thread (void *arg) |
262 { | 262 { |
263 child_process *cp; | 263 child_process *cp; |
264 | 264 |
265 /* Our identity */ | 265 /* Our identity */ |
266 cp = (child_process *)arg; | 266 cp = (child_process *)arg; |
267 | 267 |
268 /* We have to wait for the go-ahead before we can start */ | 268 /* We have to wait for the go-ahead before we can start */ |
269 if (cp == NULL | 269 if (cp == NULL |
270 || WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) | 270 || WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) |
271 return 1; | 271 return 1; |
272 | 272 |
285 return 1; | 285 return 1; |
286 } | 286 } |
287 | 287 |
288 if (rc == STATUS_READ_ERROR) | 288 if (rc == STATUS_READ_ERROR) |
289 return 1; | 289 return 1; |
290 | 290 |
291 /* If the read died, the child has died so let the thread die */ | 291 /* If the read died, the child has died so let the thread die */ |
292 if (rc == STATUS_READ_FAILED) | 292 if (rc == STATUS_READ_FAILED) |
293 break; | 293 break; |
294 | 294 |
295 /* Wait until our input is acknowledged before reading again */ | 295 /* Wait until our input is acknowledged before reading again */ |
296 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) | 296 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) |
297 { | 297 { |
298 DebPrint (("reader_thread.WaitForSingleObject failed with " | 298 DebPrint (("reader_thread.WaitForSingleObject failed with " |
299 "%lu for fd %ld\n", GetLastError (), cp->fd)); | 299 "%lu for fd %ld\n", GetLastError (), cp->fd)); |
306 /* To avoid Emacs changing directory, we just record here the directory | 306 /* To avoid Emacs changing directory, we just record here the directory |
307 the new process should start in. This is set just before calling | 307 the new process should start in. This is set just before calling |
308 sys_spawnve, and is not generally valid at any other time. */ | 308 sys_spawnve, and is not generally valid at any other time. */ |
309 static char * process_dir; | 309 static char * process_dir; |
310 | 310 |
311 static BOOL | 311 static BOOL |
312 create_child (char *exe, char *cmdline, char *env, int is_gui_app, | 312 create_child (char *exe, char *cmdline, char *env, int is_gui_app, |
313 int * pPid, child_process *cp) | 313 int * pPid, child_process *cp) |
314 { | 314 { |
315 STARTUPINFO start; | 315 STARTUPINFO start; |
316 SECURITY_ATTRIBUTES sec_attrs; | 316 SECURITY_ATTRIBUTES sec_attrs; |
317 #if 0 | 317 #if 0 |
318 SECURITY_DESCRIPTOR sec_desc; | 318 SECURITY_DESCRIPTOR sec_desc; |
319 #endif | 319 #endif |
320 DWORD flags; | 320 DWORD flags; |
321 char dir[ MAXPATHLEN ]; | 321 char dir[ MAXPATHLEN ]; |
322 | 322 |
323 if (cp == NULL) abort (); | 323 if (cp == NULL) abort (); |
324 | 324 |
325 memset (&start, 0, sizeof (start)); | 325 memset (&start, 0, sizeof (start)); |
326 start.cb = sizeof (start); | 326 start.cb = sizeof (start); |
327 | 327 |
328 #ifdef HAVE_NTGUI | 328 #ifdef HAVE_NTGUI |
329 if (NILP (Vw32_start_process_show_window) && !is_gui_app) | 329 if (NILP (Vw32_start_process_show_window) && !is_gui_app) |
330 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | 330 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; |
331 else | 331 else |
332 start.dwFlags = STARTF_USESTDHANDLES; | 332 start.dwFlags = STARTF_USESTDHANDLES; |
345 goto EH_Fail; | 345 goto EH_Fail; |
346 #endif | 346 #endif |
347 sec_attrs.nLength = sizeof (sec_attrs); | 347 sec_attrs.nLength = sizeof (sec_attrs); |
348 sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */; | 348 sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */; |
349 sec_attrs.bInheritHandle = FALSE; | 349 sec_attrs.bInheritHandle = FALSE; |
350 | 350 |
351 strcpy (dir, process_dir); | 351 strcpy (dir, process_dir); |
352 unixtodos_filename (dir); | 352 unixtodos_filename (dir); |
353 | 353 |
354 flags = (!NILP (Vw32_start_process_share_console) | 354 flags = (!NILP (Vw32_start_process_share_console) |
355 ? CREATE_NEW_PROCESS_GROUP | 355 ? CREATE_NEW_PROCESS_GROUP |
381 /* create_child doesn't know what emacs' file handle will be for waiting | 381 /* create_child doesn't know what emacs' file handle will be for waiting |
382 on output from the child, so we need to make this additional call | 382 on output from the child, so we need to make this additional call |
383 to register the handle with the process | 383 to register the handle with the process |
384 This way the select emulator knows how to match file handles with | 384 This way the select emulator knows how to match file handles with |
385 entries in child_procs. */ | 385 entries in child_procs. */ |
386 void | 386 void |
387 register_child (int pid, int fd) | 387 register_child (int pid, int fd) |
388 { | 388 { |
389 child_process *cp; | 389 child_process *cp; |
390 | 390 |
391 cp = find_child_pid (pid); | 391 cp = find_child_pid (pid); |
392 if (cp == NULL) | 392 if (cp == NULL) |
393 { | 393 { |
394 DebPrint (("register_child unable to find pid %lu\n", pid)); | 394 DebPrint (("register_child unable to find pid %lu\n", pid)); |
395 return; | 395 return; |
396 } | 396 } |
397 | 397 |
398 #ifdef FULL_DEBUG | 398 #ifdef FULL_DEBUG |
399 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid)); | 399 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid)); |
400 #endif | 400 #endif |
401 | 401 |
402 cp->fd = fd; | 402 cp->fd = fd; |
403 | 403 |
404 /* thread is initially blocked until select is called; set status so | 404 /* thread is initially blocked until select is called; set status so |
405 that select will release thread */ | 405 that select will release thread */ |
406 cp->status = STATUS_READ_ACKNOWLEDGED; | 406 cp->status = STATUS_READ_ACKNOWLEDGED; |
417 | 417 |
418 /* When a process dies its pipe will break so the reader thread will | 418 /* When a process dies its pipe will break so the reader thread will |
419 signal failure to the select emulator. | 419 signal failure to the select emulator. |
420 The select emulator then calls this routine to clean up. | 420 The select emulator then calls this routine to clean up. |
421 Since the thread signaled failure we can assume it is exiting. */ | 421 Since the thread signaled failure we can assume it is exiting. */ |
422 static void | 422 static void |
423 reap_subprocess (child_process *cp) | 423 reap_subprocess (child_process *cp) |
424 { | 424 { |
425 if (cp->procinfo.hProcess) | 425 if (cp->procinfo.hProcess) |
426 { | 426 { |
427 /* Reap the process */ | 427 /* Reap the process */ |
446 | 446 |
447 /* Wait for any of our existing child processes to die | 447 /* Wait for any of our existing child processes to die |
448 When it does, close its handle | 448 When it does, close its handle |
449 Return the pid and fill in the status if non-NULL. */ | 449 Return the pid and fill in the status if non-NULL. */ |
450 | 450 |
451 int | 451 int |
452 sys_wait (int *status) | 452 sys_wait (int *status) |
453 { | 453 { |
454 DWORD active, retval; | 454 DWORD active, retval; |
455 int nh; | 455 int nh; |
456 int pid; | 456 int pid; |
457 child_process *cp, *cps[MAX_CHILDREN]; | 457 child_process *cp, *cps[MAX_CHILDREN]; |
458 HANDLE wait_hnd[MAX_CHILDREN]; | 458 HANDLE wait_hnd[MAX_CHILDREN]; |
459 | 459 |
460 nh = 0; | 460 nh = 0; |
461 if (dead_child != NULL) | 461 if (dead_child != NULL) |
462 { | 462 { |
463 /* We want to wait for a specific child */ | 463 /* We want to wait for a specific child */ |
464 wait_hnd[nh] = dead_child->procinfo.hProcess; | 464 wait_hnd[nh] = dead_child->procinfo.hProcess; |
477 wait_hnd[nh] = cp->procinfo.hProcess; | 477 wait_hnd[nh] = cp->procinfo.hProcess; |
478 cps[nh] = cp; | 478 cps[nh] = cp; |
479 nh++; | 479 nh++; |
480 } | 480 } |
481 } | 481 } |
482 | 482 |
483 if (nh == 0) | 483 if (nh == 0) |
484 { | 484 { |
485 /* Nothing to wait on, so fail */ | 485 /* Nothing to wait on, so fail */ |
486 errno = ECHILD; | 486 errno = ECHILD; |
487 return -1; | 487 return -1; |
533 | 533 |
534 if (retval == STATUS_CONTROL_C_EXIT) | 534 if (retval == STATUS_CONTROL_C_EXIT) |
535 retval = SIGINT; | 535 retval = SIGINT; |
536 else | 536 else |
537 retval <<= 8; | 537 retval <<= 8; |
538 | 538 |
539 cp = cps[active]; | 539 cp = cps[active]; |
540 pid = cp->pid; | 540 pid = cp->pid; |
541 #ifdef FULL_DEBUG | 541 #ifdef FULL_DEBUG |
542 DebPrint (("Wait signaled with process pid %d\n", cp->pid)); | 542 DebPrint (("Wait signaled with process pid %d\n", cp->pid)); |
543 #endif | 543 #endif |
569 | 569 |
570 reap_subprocess (cp); | 570 reap_subprocess (cp); |
571 } | 571 } |
572 | 572 |
573 reap_subprocess (cp); | 573 reap_subprocess (cp); |
574 | 574 |
575 return pid; | 575 return pid; |
576 } | 576 } |
577 | 577 |
578 void | 578 void |
579 w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int * is_gui_app) | 579 w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int * is_gui_app) |
580 { | 580 { |
581 file_data executable; | 581 file_data executable; |
582 char * p; | 582 char * p; |
583 | 583 |
584 /* Default values in case we can't tell for sure. */ | 584 /* Default values in case we can't tell for sure. */ |
585 *is_dos_app = FALSE; | 585 *is_dos_app = FALSE; |
586 *is_cygnus_app = FALSE; | 586 *is_cygnus_app = FALSE; |
587 *is_gui_app = FALSE; | 587 *is_gui_app = FALSE; |
588 | 588 |
589 if (!open_input_file (&executable, filename)) | 589 if (!open_input_file (&executable, filename)) |
590 return; | 590 return; |
591 | 591 |
592 p = strrchr (filename, '.'); | 592 p = strrchr (filename, '.'); |
593 | 593 |
594 /* We can only identify DOS .com programs from the extension. */ | 594 /* We can only identify DOS .com programs from the extension. */ |
595 if (p && stricmp (p, ".com") == 0) | 595 if (p && stricmp (p, ".com") == 0) |
596 *is_dos_app = TRUE; | 596 *is_dos_app = TRUE; |
597 else if (p && (stricmp (p, ".bat") == 0 | 597 else if (p && (stricmp (p, ".bat") == 0 |
598 || stricmp (p, ".cmd") == 0)) | 598 || stricmp (p, ".cmd") == 0)) |
621 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | 621 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) |
622 goto unwind; | 622 goto unwind; |
623 | 623 |
624 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew); | 624 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew); |
625 | 625 |
626 if ((char *) nt_header > (char *) dos_header + executable.size) | 626 if ((char *) nt_header > (char *) dos_header + executable.size) |
627 { | 627 { |
628 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | 628 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ |
629 *is_dos_app = TRUE; | 629 *is_dos_app = TRUE; |
630 } | 630 } |
631 else if (nt_header->Signature != IMAGE_NT_SIGNATURE | 631 else if (nt_header->Signature != IMAGE_NT_SIGNATURE |
632 && LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | 632 && LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) |
633 { | 633 { |
634 *is_dos_app = TRUE; | 634 *is_dos_app = TRUE; |
635 } | 635 } |
662 GUI) app. Accept Posix and OS2 subsytem apps as console | 662 GUI) app. Accept Posix and OS2 subsytem apps as console |
663 apps. */ | 663 apps. */ |
664 *is_gui_app = (nt_header->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI); | 664 *is_gui_app = (nt_header->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI); |
665 } | 665 } |
666 } | 666 } |
667 | 667 |
668 unwind: | 668 unwind: |
669 close_file_data (&executable); | 669 close_file_data (&executable); |
670 } | 670 } |
671 | 671 |
672 int | 672 int |
715 *nptr = NULL; | 715 *nptr = NULL; |
716 } | 716 } |
717 | 717 |
718 /* When a new child process is created we need to register it in our list, | 718 /* When a new child process is created we need to register it in our list, |
719 so intercept spawn requests. */ | 719 so intercept spawn requests. */ |
720 int | 720 int |
721 sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | 721 sys_spawnve (int mode, char *cmdname, char **argv, char **envp) |
722 { | 722 { |
723 Lisp_Object program, full; | 723 Lisp_Object program, full; |
724 char *cmdline, *env, *parg, **targ; | 724 char *cmdline, *env, *parg, **targ; |
725 int arglen, numenv; | 725 int arglen, numenv; |
744 /* Handle executable names without an executable suffix. */ | 744 /* Handle executable names without an executable suffix. */ |
745 program = make_string (cmdname, strlen (cmdname)); | 745 program = make_string (cmdname, strlen (cmdname)); |
746 if (NILP (Ffile_executable_p (program))) | 746 if (NILP (Ffile_executable_p (program))) |
747 { | 747 { |
748 struct gcpro gcpro1; | 748 struct gcpro gcpro1; |
749 | 749 |
750 full = Qnil; | 750 full = Qnil; |
751 GCPRO1 (program); | 751 GCPRO1 (program); |
752 openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK)); | 752 openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK)); |
753 UNGCPRO; | 753 UNGCPRO; |
754 if (NILP (full)) | 754 if (NILP (full)) |
787 strcpy (cmdname, SDATA (Vinvocation_directory)); | 787 strcpy (cmdname, SDATA (Vinvocation_directory)); |
788 strcat (cmdname, "cmdproxy.exe"); | 788 strcat (cmdname, "cmdproxy.exe"); |
789 } | 789 } |
790 unixtodos_filename (cmdname); | 790 unixtodos_filename (cmdname); |
791 } | 791 } |
792 | 792 |
793 /* we have to do some conjuring here to put argv and envp into the | 793 /* we have to do some conjuring here to put argv and envp into the |
794 form CreateProcess wants... argv needs to be a space separated/null | 794 form CreateProcess wants... argv needs to be a space separated/null |
795 terminated list of parameters, and envp is a null | 795 terminated list of parameters, and envp is a null |
796 separated/double-null terminated list of parameters. | 796 separated/double-null terminated list of parameters. |
797 | 797 |
828 if (INTEGERP (Vw32_quote_process_args)) | 828 if (INTEGERP (Vw32_quote_process_args)) |
829 escape_char = XINT (Vw32_quote_process_args); | 829 escape_char = XINT (Vw32_quote_process_args); |
830 else | 830 else |
831 escape_char = is_cygnus_app ? '"' : '\\'; | 831 escape_char = is_cygnus_app ? '"' : '\\'; |
832 } | 832 } |
833 | 833 |
834 /* Cygwin apps needs quoting a bit more often */ | 834 /* Cygwin apps needs quoting a bit more often */ |
835 if (escape_char == '"') | 835 if (escape_char == '"') |
836 sepchars = "\r\n\t\f '"; | 836 sepchars = "\r\n\t\f '"; |
837 | 837 |
838 /* do argv... */ | 838 /* do argv... */ |
839 arglen = 0; | 839 arglen = 0; |
964 } | 964 } |
965 *parg++ = ' '; | 965 *parg++ = ' '; |
966 targ++; | 966 targ++; |
967 } | 967 } |
968 *--parg = '\0'; | 968 *--parg = '\0'; |
969 | 969 |
970 /* and envp... */ | 970 /* and envp... */ |
971 arglen = 1; | 971 arglen = 1; |
972 targ = envp; | 972 targ = envp; |
973 numenv = 1; /* for end null */ | 973 numenv = 1; /* for end null */ |
974 while (*targ) | 974 while (*targ) |
975 { | 975 { |
976 arglen += strlen (*targ++) + 1; | 976 arglen += strlen (*targ++) + 1; |
977 numenv++; | 977 numenv++; |
978 } | 978 } |
979 /* extra env vars... */ | 979 /* extra env vars... */ |
980 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", | 980 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", |
981 GetCurrentProcessId ()); | 981 GetCurrentProcessId ()); |
982 arglen += strlen (ppid_env_var_buffer) + 1; | 982 arglen += strlen (ppid_env_var_buffer) + 1; |
983 numenv++; | 983 numenv++; |
984 | 984 |
985 /* merge env passed in and extra env into one, and sort it. */ | 985 /* merge env passed in and extra env into one, and sort it. */ |
1002 if (cp == NULL) | 1002 if (cp == NULL) |
1003 { | 1003 { |
1004 errno = EAGAIN; | 1004 errno = EAGAIN; |
1005 return -1; | 1005 return -1; |
1006 } | 1006 } |
1007 | 1007 |
1008 /* Now create the process. */ | 1008 /* Now create the process. */ |
1009 if (!create_child (cmdname, cmdline, env, is_gui_app, &pid, cp)) | 1009 if (!create_child (cmdname, cmdline, env, is_gui_app, &pid, cp)) |
1010 { | 1010 { |
1011 delete_child (cp); | 1011 delete_child (cp); |
1012 errno = ENOEXEC; | 1012 errno = ENOEXEC; |
1013 return -1; | 1013 return -1; |
1014 } | 1014 } |
1015 | 1015 |
1016 return pid; | 1016 return pid; |
1017 } | 1017 } |
1018 | 1018 |
1019 /* Emulate the select call | 1019 /* Emulate the select call |
1020 Wait for available input on any of the given rfds, or timeout if | 1020 Wait for available input on any of the given rfds, or timeout if |
1041 extern HANDLE interrupt_handle; | 1041 extern HANDLE interrupt_handle; |
1042 | 1042 |
1043 /* From process.c */ | 1043 /* From process.c */ |
1044 extern int proc_buffered_char[]; | 1044 extern int proc_buffered_char[]; |
1045 | 1045 |
1046 int | 1046 int |
1047 sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, | 1047 sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, |
1048 EMACS_TIME *timeout) | 1048 EMACS_TIME *timeout) |
1049 { | 1049 { |
1050 SELECT_TYPE orfds; | 1050 SELECT_TYPE orfds; |
1051 DWORD timeout_ms, start_time; | 1051 DWORD timeout_ms, start_time; |
1052 int i, nh, nc, nr; | 1052 int i, nh, nc, nr; |
1053 DWORD active; | 1053 DWORD active; |
1054 child_process *cp, *cps[MAX_CHILDREN]; | 1054 child_process *cp, *cps[MAX_CHILDREN]; |
1055 HANDLE wait_hnd[MAXDESC + MAX_CHILDREN]; | 1055 HANDLE wait_hnd[MAXDESC + MAX_CHILDREN]; |
1056 int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ | 1056 int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ |
1057 | 1057 |
1058 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; | 1058 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; |
1059 | 1059 |
1060 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ | 1060 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ |
1061 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) | 1061 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) |
1062 { | 1062 { |
1063 Sleep (timeout_ms); | 1063 Sleep (timeout_ms); |
1064 return 0; | 1064 return 0; |
1065 } | 1065 } |
1066 | 1066 |
1068 if (rfds == NULL || wfds != NULL || efds != NULL) | 1068 if (rfds == NULL || wfds != NULL || efds != NULL) |
1069 { | 1069 { |
1070 errno = EINVAL; | 1070 errno = EINVAL; |
1071 return -1; | 1071 return -1; |
1072 } | 1072 } |
1073 | 1073 |
1074 orfds = *rfds; | 1074 orfds = *rfds; |
1075 FD_ZERO (rfds); | 1075 FD_ZERO (rfds); |
1076 nr = 0; | 1076 nr = 0; |
1077 | 1077 |
1078 /* Always wait on interrupt_handle, to detect C-g (quit). */ | 1078 /* Always wait on interrupt_handle, to detect C-g (quit). */ |
1079 wait_hnd[0] = interrupt_handle; | 1079 wait_hnd[0] = interrupt_handle; |
1080 fdindex[0] = -1; | 1080 fdindex[0] = -1; |
1081 | 1081 |
1082 /* Build a list of pipe handles to wait on. */ | 1082 /* Build a list of pipe handles to wait on. */ |
1083 nh = 1; | 1083 nh = 1; |
1084 for (i = 0; i < nfds; i++) | 1084 for (i = 0; i < nfds; i++) |
1085 if (FD_ISSET (i, &orfds)) | 1085 if (FD_ISSET (i, &orfds)) |
1086 { | 1086 { |
1193 { | 1193 { |
1194 wait_hnd[nh + nc] = cp->procinfo.hProcess; | 1194 wait_hnd[nh + nc] = cp->procinfo.hProcess; |
1195 cps[nc] = cp; | 1195 cps[nc] = cp; |
1196 nc++; | 1196 nc++; |
1197 } | 1197 } |
1198 | 1198 |
1199 /* Nothing to look for, so we didn't find anything */ | 1199 /* Nothing to look for, so we didn't find anything */ |
1200 if (nh + nc == 0) | 1200 if (nh + nc == 0) |
1201 { | 1201 { |
1202 if (timeout) | 1202 if (timeout) |
1203 Sleep (timeout_ms); | 1203 Sleep (timeout_ms); |
1204 return 0; | 1204 return 0; |
1205 } | 1205 } |
1206 | 1206 |
1207 start_time = GetTickCount (); | 1207 start_time = GetTickCount (); |
1208 | 1208 |
1209 /* Wait for input or child death to be signalled. If user input is | 1209 /* Wait for input or child death to be signalled. If user input is |
1210 allowed, then also accept window messages. */ | 1210 allowed, then also accept window messages. */ |
1211 if (FD_ISSET (0, &orfds)) | 1211 if (FD_ISSET (0, &orfds)) |
1360 } | 1360 } |
1361 /* keep looking */ | 1361 /* keep looking */ |
1362 return TRUE; | 1362 return TRUE; |
1363 } | 1363 } |
1364 | 1364 |
1365 int | 1365 int |
1366 sys_kill (int pid, int sig) | 1366 sys_kill (int pid, int sig) |
1367 { | 1367 { |
1368 child_process *cp; | 1368 child_process *cp; |
1369 HANDLE proc_hand; | 1369 HANDLE proc_hand; |
1370 int need_to_free = 0; | 1370 int need_to_free = 0; |
1371 int rc = 0; | 1371 int rc = 0; |
1372 | 1372 |
1373 /* Only handle signals that will result in the process dying */ | 1373 /* Only handle signals that will result in the process dying */ |
1374 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) | 1374 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) |
1375 { | 1375 { |
1376 errno = EINVAL; | 1376 errno = EINVAL; |
1377 return -1; | 1377 return -1; |
1394 pid = cp->procinfo.dwProcessId; | 1394 pid = cp->procinfo.dwProcessId; |
1395 | 1395 |
1396 /* Try to locate console window for process. */ | 1396 /* Try to locate console window for process. */ |
1397 EnumWindows (find_child_console, (LPARAM) cp); | 1397 EnumWindows (find_child_console, (LPARAM) cp); |
1398 } | 1398 } |
1399 | 1399 |
1400 if (sig == SIGINT || sig == SIGQUIT) | 1400 if (sig == SIGINT || sig == SIGQUIT) |
1401 { | 1401 { |
1402 if (NILP (Vw32_start_process_share_console) && cp && cp->hwnd) | 1402 if (NILP (Vw32_start_process_share_console) && cp && cp->hwnd) |
1403 { | 1403 { |
1404 BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0); | 1404 BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0); |
1570 handles[0] = GetStdHandle (STD_INPUT_HANDLE); | 1570 handles[0] = GetStdHandle (STD_INPUT_HANDLE); |
1571 handles[1] = GetStdHandle (STD_OUTPUT_HANDLE); | 1571 handles[1] = GetStdHandle (STD_OUTPUT_HANDLE); |
1572 handles[2] = GetStdHandle (STD_ERROR_HANDLE); | 1572 handles[2] = GetStdHandle (STD_ERROR_HANDLE); |
1573 | 1573 |
1574 /* make inheritable copies of the new handles */ | 1574 /* make inheritable copies of the new handles */ |
1575 if (!DuplicateHandle (parent, | 1575 if (!DuplicateHandle (parent, |
1576 (HANDLE) _get_osfhandle (in), | 1576 (HANDLE) _get_osfhandle (in), |
1577 parent, | 1577 parent, |
1578 &newstdin, | 1578 &newstdin, |
1579 0, | 1579 0, |
1580 TRUE, | 1580 TRUE, |
1581 DUPLICATE_SAME_ACCESS)) | 1581 DUPLICATE_SAME_ACCESS)) |
1582 report_file_error ("Duplicating input handle for child", Qnil); | 1582 report_file_error ("Duplicating input handle for child", Qnil); |
1583 | 1583 |
1584 if (!DuplicateHandle (parent, | 1584 if (!DuplicateHandle (parent, |
1585 (HANDLE) _get_osfhandle (out), | 1585 (HANDLE) _get_osfhandle (out), |
1586 parent, | 1586 parent, |
1587 &newstdout, | 1587 &newstdout, |
1588 0, | 1588 0, |
1589 TRUE, | 1589 TRUE, |
1590 DUPLICATE_SAME_ACCESS)) | 1590 DUPLICATE_SAME_ACCESS)) |
1591 report_file_error ("Duplicating output handle for child", Qnil); | 1591 report_file_error ("Duplicating output handle for child", Qnil); |
1592 | 1592 |
1593 if (!DuplicateHandle (parent, | 1593 if (!DuplicateHandle (parent, |
1594 (HANDLE) _get_osfhandle (err), | 1594 (HANDLE) _get_osfhandle (err), |
1595 parent, | 1595 parent, |
1596 &newstderr, | 1596 &newstderr, |
1597 0, | 1597 0, |
1600 report_file_error ("Duplicating error handle for child", Qnil); | 1600 report_file_error ("Duplicating error handle for child", Qnil); |
1601 | 1601 |
1602 /* and store them as our std handles */ | 1602 /* and store them as our std handles */ |
1603 if (!SetStdHandle (STD_INPUT_HANDLE, newstdin)) | 1603 if (!SetStdHandle (STD_INPUT_HANDLE, newstdin)) |
1604 report_file_error ("Changing stdin handle", Qnil); | 1604 report_file_error ("Changing stdin handle", Qnil); |
1605 | 1605 |
1606 if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout)) | 1606 if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout)) |
1607 report_file_error ("Changing stdout handle", Qnil); | 1607 report_file_error ("Changing stdout handle", Qnil); |
1608 | 1608 |
1609 if (!SetStdHandle (STD_ERROR_HANDLE, newstderr)) | 1609 if (!SetStdHandle (STD_ERROR_HANDLE, newstderr)) |
1610 report_file_error ("Changing stderr handle", Qnil); | 1610 report_file_error ("Changing stderr handle", Qnil); |
1931 if (NILP (userp)) | 1931 if (NILP (userp)) |
1932 return make_number (GetSystemDefaultLCID ()); | 1932 return make_number (GetSystemDefaultLCID ()); |
1933 return make_number (GetUserDefaultLCID ()); | 1933 return make_number (GetUserDefaultLCID ()); |
1934 } | 1934 } |
1935 | 1935 |
1936 | 1936 |
1937 DEFUN ("w32-set-current-locale", Fw32_set_current_locale, Sw32_set_current_locale, 1, 1, 0, | 1937 DEFUN ("w32-set-current-locale", Fw32_set_current_locale, Sw32_set_current_locale, 1, 1, 0, |
1938 doc: /* Make Windows locale LCID be the current locale setting for Emacs. | 1938 doc: /* Make Windows locale LCID be the current locale setting for Emacs. |
1939 If successful, the new locale id is returned, otherwise nil. */) | 1939 If successful, the new locale id is returned, otherwise nil. */) |
1940 (lcid) | 1940 (lcid) |
1941 Lisp_Object lcid; | 1941 Lisp_Object lcid; |
1988 () | 1988 () |
1989 { | 1989 { |
1990 return make_number (GetConsoleCP ()); | 1990 return make_number (GetConsoleCP ()); |
1991 } | 1991 } |
1992 | 1992 |
1993 | 1993 |
1994 DEFUN ("w32-set-console-codepage", Fw32_set_console_codepage, | 1994 DEFUN ("w32-set-console-codepage", Fw32_set_console_codepage, |
1995 Sw32_set_console_codepage, 1, 1, 0, | 1995 Sw32_set_console_codepage, 1, 1, 0, |
1996 doc: /* Make Windows codepage CP be the current codepage setting for Emacs. | 1996 doc: /* Make Windows codepage CP be the current codepage setting for Emacs. |
1997 The codepage setting affects keyboard input and display in tty mode. | 1997 The codepage setting affects keyboard input and display in tty mode. |
1998 If successful, the new CP is returned, otherwise nil. */) | 1998 If successful, the new CP is returned, otherwise nil. */) |
2017 () | 2017 () |
2018 { | 2018 { |
2019 return make_number (GetConsoleOutputCP ()); | 2019 return make_number (GetConsoleOutputCP ()); |
2020 } | 2020 } |
2021 | 2021 |
2022 | 2022 |
2023 DEFUN ("w32-set-console-output-codepage", Fw32_set_console_output_codepage, | 2023 DEFUN ("w32-set-console-output-codepage", Fw32_set_console_output_codepage, |
2024 Sw32_set_console_output_codepage, 1, 1, 0, | 2024 Sw32_set_console_output_codepage, 1, 1, 0, |
2025 doc: /* Make Windows codepage CP be the current codepage setting for Emacs. | 2025 doc: /* Make Windows codepage CP be the current codepage setting for Emacs. |
2026 The codepage setting affects keyboard input and display in tty mode. | 2026 The codepage setting affects keyboard input and display in tty mode. |
2027 If successful, the new CP is returned, otherwise nil. */) | 2027 If successful, the new CP is returned, otherwise nil. */) |
2097 | 2097 |
2098 return Fcons (make_number (kl & 0xffff), | 2098 return Fcons (make_number (kl & 0xffff), |
2099 make_number ((kl >> 16) & 0xffff)); | 2099 make_number ((kl >> 16) & 0xffff)); |
2100 } | 2100 } |
2101 | 2101 |
2102 | 2102 |
2103 DEFUN ("w32-set-keyboard-layout", Fw32_set_keyboard_layout, | 2103 DEFUN ("w32-set-keyboard-layout", Fw32_set_keyboard_layout, |
2104 Sw32_set_keyboard_layout, 1, 1, 0, | 2104 Sw32_set_keyboard_layout, 1, 1, 0, |
2105 doc: /* Make LAYOUT be the current keyboard layout for Emacs. | 2105 doc: /* Make LAYOUT be the current keyboard layout for Emacs. |
2106 The keyboard layout setting affects interpretation of keyboard input. | 2106 The keyboard layout setting affects interpretation of keyboard input. |
2107 If successful, the new layout id is returned, otherwise nil. */) | 2107 If successful, the new layout id is returned, otherwise nil. */) |
2216 DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names, | 2216 DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names, |
2217 doc: /* Non-nil means convert all-upper case file names to lower case. | 2217 doc: /* Non-nil means convert all-upper case file names to lower case. |
2218 This applies when performing completions and file name expansion. | 2218 This applies when performing completions and file name expansion. |
2219 Note that the value of this setting also affects remote file names, | 2219 Note that the value of this setting also affects remote file names, |
2220 so you probably don't want to set to non-nil if you use case-sensitive | 2220 so you probably don't want to set to non-nil if you use case-sensitive |
2221 filesystems via ange-ftp. */); | 2221 filesystems via ange-ftp. */); |
2222 Vw32_downcase_file_names = Qnil; | 2222 Vw32_downcase_file_names = Qnil; |
2223 | 2223 |
2224 #if 0 | 2224 #if 0 |
2225 DEFVAR_LISP ("w32-generate-fake-inodes", &Vw32_generate_fake_inodes, | 2225 DEFVAR_LISP ("w32-generate-fake-inodes", &Vw32_generate_fake_inodes, |
2226 doc: /* Non-nil means attempt to fake realistic inode values. | 2226 doc: /* Non-nil means attempt to fake realistic inode values. |