Mercurial > hg > xemacs-beta
comparison src/process-nt.c @ 854:1d8fb2eee1bb
[xemacs-hg @ 2002-05-28 16:06:58 by didierv]
Fix header inclusion order
author | didierv |
---|---|
date | Tue, 28 May 2002 16:07:03 +0000 |
parents | 2b6fa2618f76 |
children | 84762348c6f9 |
comparison
equal
deleted
inserted
replaced
853:2b6fa2618f76 | 854:1d8fb2eee1bb |
---|---|
32 #include "hash.h" | 32 #include "hash.h" |
33 #include "lstream.h" | 33 #include "lstream.h" |
34 #include "process.h" | 34 #include "process.h" |
35 #include "procimpl.h" | 35 #include "procimpl.h" |
36 | 36 |
37 #include "syssignal.h" | 37 #include "syssignal.h" /* Always include before sysproc.h -- didier */ |
38 #include "sysfile.h" | 38 #include "sysfile.h" |
39 #include "sysproc.h" | 39 #include "sysproc.h" |
40 | 40 |
41 /* Bound by win32-native.el */ | 41 /* Bound by win32-native.el */ |
42 Lisp_Object Qmswindows_construct_process_command_line; | 42 Lisp_Object Qmswindows_construct_process_command_line; |
125 * further by other routines. Return nonzero if successful. | 125 * further by other routines. Return nonzero if successful. |
126 * | 126 * |
127 * The memory in other process is allocated by creating a suspended | 127 * The memory in other process is allocated by creating a suspended |
128 * thread. Initial stack of that thread is used as the memory | 128 * thread. Initial stack of that thread is used as the memory |
129 * block. The thread entry point is the routine ExitThread in | 129 * block. The thread entry point is the routine ExitThread in |
130 * kernel32.dll, so the allocated memory is freed just by resuming the | 130 * kernel32.dll, so the allocated memory is freed just by resuming the |
131 * thread, which immediately terminates after that. | 131 * thread, which immediately terminates after that. |
132 */ | 132 */ |
133 | 133 |
134 static int | 134 static int |
135 alloc_process_memory (HANDLE h_process, Bytecount size, | 135 alloc_process_memory (HANDLE h_process, Bytecount size, |
136 process_memory *pmc) | 136 process_memory *pmc) |
137 { | 137 { |
138 LPTHREAD_START_ROUTINE adr_ExitThread = | 138 LPTHREAD_START_ROUTINE adr_ExitThread = |
139 (LPTHREAD_START_ROUTINE) | 139 (LPTHREAD_START_ROUTINE) |
333 { | 333 { |
334 HANDLE h_process; | 334 HANDLE h_process; |
335 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32")); | 335 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32")); |
336 int close_process = 0; | 336 int close_process = 0; |
337 DWORD retval; | 337 DWORD retval; |
338 | 338 |
339 assert (h_kernel != NULL); | 339 assert (h_kernel != NULL); |
340 | 340 |
341 if (cp) | 341 if (cp) |
342 { | 342 { |
343 pid = cp->dwProcessId; | 343 pid = cp->dwProcessId; |
344 h_process = cp->h_process; | 344 h_process = cp->h_process; |
345 } | 345 } |
346 else | 346 else |
347 { | 347 { |
348 close_process = 1; | 348 close_process = 1; |
349 /* Try to open the process with required privileges */ | 349 /* Try to open the process with required privileges */ |
350 h_process = OpenProcess (PROCESS_CREATE_THREAD | 350 h_process = OpenProcess (PROCESS_CREATE_THREAD |
351 | PROCESS_QUERY_INFORMATION | 351 | PROCESS_QUERY_INFORMATION |
352 | PROCESS_VM_OPERATION | 352 | PROCESS_VM_OPERATION |
353 | PROCESS_VM_WRITE, | 353 | PROCESS_VM_WRITE, |
354 FALSE, pid); | 354 FALSE, pid); |
355 if (!h_process) | 355 if (!h_process) |
356 return 0; | 356 return 0; |
366 sigkill_data d; | 366 sigkill_data d; |
367 | 367 |
368 d.adr_ExitProcess = | 368 d.adr_ExitProcess = |
369 (void (WINAPI *) (UINT)) GetProcAddress (h_kernel, "ExitProcess"); | 369 (void (WINAPI *) (UINT)) GetProcAddress (h_kernel, "ExitProcess"); |
370 assert (d.adr_ExitProcess); | 370 assert (d.adr_ExitProcess); |
371 retval = run_in_other_process (h_process, | 371 retval = run_in_other_process (h_process, |
372 (LPTHREAD_START_ROUTINE) sigkill_proc, | 372 (LPTHREAD_START_ROUTINE) sigkill_proc, |
373 &d, sizeof (d)); | 373 &d, sizeof (d)); |
374 break; | 374 break; |
375 } | 375 } |
376 case SIGINT: | 376 case SIGINT: |
379 d.adr_GenerateConsoleCtrlEvent = | 379 d.adr_GenerateConsoleCtrlEvent = |
380 (BOOL (WINAPI *) (DWORD, DWORD)) | 380 (BOOL (WINAPI *) (DWORD, DWORD)) |
381 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); | 381 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); |
382 assert (d.adr_GenerateConsoleCtrlEvent); | 382 assert (d.adr_GenerateConsoleCtrlEvent); |
383 d.event = CTRL_C_EVENT; | 383 d.event = CTRL_C_EVENT; |
384 retval = run_in_other_process (h_process, | 384 retval = run_in_other_process (h_process, |
385 (LPTHREAD_START_ROUTINE) sigint_proc, | 385 (LPTHREAD_START_ROUTINE) sigint_proc, |
386 &d, sizeof (d)); | 386 &d, sizeof (d)); |
387 break; | 387 break; |
388 } | 388 } |
389 default: | 389 default: |
401 static void | 401 static void |
402 enable_child_signals (HANDLE h_process) | 402 enable_child_signals (HANDLE h_process) |
403 { | 403 { |
404 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32")); | 404 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32")); |
405 sig_enable_data d; | 405 sig_enable_data d; |
406 | 406 |
407 assert (h_kernel != NULL); | 407 assert (h_kernel != NULL); |
408 d.adr_SetConsoleCtrlHandler = | 408 d.adr_SetConsoleCtrlHandler = |
409 (BOOL (WINAPI *) (LPVOID, BOOL)) | 409 (BOOL (WINAPI *) (LPVOID, BOOL)) |
410 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); | 410 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); |
411 assert (d.adr_SetConsoleCtrlHandler); | 411 assert (d.adr_SetConsoleCtrlHandler); |
412 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc, | 412 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc, |
413 &d, sizeof (d)); | 413 &d, sizeof (d)); |
414 } | 414 } |
415 | 415 |
416 /* ---------------------------- the 95 way ------------------------------- */ | 416 /* ---------------------------- the 95 way ------------------------------- */ |
417 | 417 |
418 static BOOL CALLBACK | 418 static BOOL CALLBACK |
419 find_child_console (HWND hwnd, long putada) | 419 find_child_console (HWND hwnd, long putada) |
420 { | 420 { |
446 send_signal_the_95_way (struct nt_process_data *cp, int pid, int signo) | 446 send_signal_the_95_way (struct nt_process_data *cp, int pid, int signo) |
447 { | 447 { |
448 HANDLE h_process; | 448 HANDLE h_process; |
449 int close_process = 0; | 449 int close_process = 0; |
450 int rc = 1; | 450 int rc = 1; |
451 | 451 |
452 if (cp) | 452 if (cp) |
453 { | 453 { |
454 pid = cp->dwProcessId; | 454 pid = cp->dwProcessId; |
455 h_process = cp->h_process; | 455 h_process = cp->h_process; |
456 | 456 |
463 /* Try to open the process with required privileges */ | 463 /* Try to open the process with required privileges */ |
464 h_process = OpenProcess (PROCESS_TERMINATE, FALSE, pid); | 464 h_process = OpenProcess (PROCESS_TERMINATE, FALSE, pid); |
465 if (!h_process) | 465 if (!h_process) |
466 return 0; | 466 return 0; |
467 } | 467 } |
468 | 468 |
469 if (signo == SIGINT) | 469 if (signo == SIGINT) |
470 { | 470 { |
471 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd) | 471 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd) |
472 { | 472 { |
473 BYTE control_scan_code = (BYTE) MapVirtualKeyA (VK_CONTROL, 0); | 473 BYTE control_scan_code = (BYTE) MapVirtualKeyA (VK_CONTROL, 0); |
632 if (signo != SIGKILL && signo != SIGTERM | 632 if (signo != SIGKILL && signo != SIGTERM |
633 && signo != SIGQUIT && signo != SIGINT | 633 && signo != SIGQUIT && signo != SIGINT |
634 && signo != SIGHUP) | 634 && signo != SIGHUP) |
635 invalid_constant ("Signal number not supported", make_int (signo)); | 635 invalid_constant ("Signal number not supported", make_int (signo)); |
636 } | 636 } |
637 | 637 |
638 /*-----------------------------------------------------------------------*/ | 638 /*-----------------------------------------------------------------------*/ |
639 /* Process methods */ | 639 /* Process methods */ |
640 /*-----------------------------------------------------------------------*/ | 640 /*-----------------------------------------------------------------------*/ |
641 | 641 |
642 /* | 642 /* |
784 /* Decide whether to do I/O on process handles, or just mark the | 784 /* Decide whether to do I/O on process handles, or just mark the |
785 process exited immediately upon successful launching. We do I/O if the | 785 process exited immediately upon successful launching. We do I/O if the |
786 process is a console one, or if it is windowed but windowed_process_io | 786 process is a console one, or if it is windowed but windowed_process_io |
787 is non-zero */ | 787 is non-zero */ |
788 do_io = !windowed || windowed_process_io ; | 788 do_io = !windowed || windowed_process_io ; |
789 | 789 |
790 if (do_io) | 790 if (do_io) |
791 { | 791 { |
792 /* Create two unidirectional named pipes */ | 792 /* Create two unidirectional named pipes */ |
793 HANDLE htmp; | 793 HANDLE htmp; |
794 SECURITY_ATTRIBUTES sa; | 794 SECURITY_ATTRIBUTES sa; |
862 { | 862 { |
863 Intbyte **env; | 863 Intbyte **env; |
864 REGISTER Lisp_Object tem; | 864 REGISTER Lisp_Object tem; |
865 REGISTER Intbyte **new_env; | 865 REGISTER Intbyte **new_env; |
866 REGISTER int new_length = 0, i; | 866 REGISTER int new_length = 0, i; |
867 | 867 |
868 for (tem = Vprocess_environment; | 868 for (tem = Vprocess_environment; |
869 (CONSP (tem) | 869 (CONSP (tem) |
870 && STRINGP (XCAR (tem))); | 870 && STRINGP (XCAR (tem))); |
871 tem = XCDR (tem)) | 871 tem = XCDR (tem)) |
872 new_length++; | 872 new_length++; |
874 /* FSF adds an extra env var to hold the current process ID of the | 874 /* FSF adds an extra env var to hold the current process ID of the |
875 Emacs process. Apparently this is used only by emacsserver.c, | 875 Emacs process. Apparently this is used only by emacsserver.c, |
876 which we have superseded by gnuserv.c. (#### Does it work under | 876 which we have superseded by gnuserv.c. (#### Does it work under |
877 MS Windows?) | 877 MS Windows?) |
878 | 878 |
879 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", | 879 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d", |
880 GetCurrentProcessId ()); | 880 GetCurrentProcessId ()); |
881 arglen += strlen (ppid_env_var_buffer) + 1; | 881 arglen += strlen (ppid_env_var_buffer) + 1; |
882 numenv++; | 882 numenv++; |
883 */ | 883 */ |
884 | 884 |
885 /* new_length + 1 to include terminating 0. */ | 885 /* new_length + 1 to include terminating 0. */ |
886 env = new_env = alloca_array (Intbyte *, new_length + 1); | 886 env = new_env = alloca_array (Intbyte *, new_length + 1); |
887 | 887 |
888 /* Copy the Vprocess_environment strings into new_env. */ | 888 /* Copy the Vprocess_environment strings into new_env. */ |
889 for (tem = Vprocess_environment; | 889 for (tem = Vprocess_environment; |
890 (CONSP (tem) | 890 (CONSP (tem) |
891 && STRINGP (XCAR (tem))); | 891 && STRINGP (XCAR (tem))); |
892 tem = XCDR (tem)) | 892 tem = XCDR (tem)) |
914 } | 914 } |
915 *new_env++ = string; | 915 *new_env++ = string; |
916 duplicate: ; | 916 duplicate: ; |
917 } | 917 } |
918 *new_env = 0; | 918 *new_env = 0; |
919 | 919 |
920 /* Sort the environment variables */ | 920 /* Sort the environment variables */ |
921 new_length = new_env - env; | 921 new_length = new_env - env; |
922 qsort (env, new_length, sizeof (Intbyte *), mswindows_compare_env); | 922 qsort (env, new_length, sizeof (Intbyte *), mswindows_compare_env); |
923 | 923 |
924 { | 924 { |
951 qxestrcpy (cmdname, XSTRING_DATA (Vinvocation_directory)); | 951 qxestrcpy (cmdname, XSTRING_DATA (Vinvocation_directory)); |
952 qxestrcat (cmdname, (Intbyte *) "cmdproxy.exe"); | 952 qxestrcat (cmdname, (Intbyte *) "cmdproxy.exe"); |
953 } | 953 } |
954 } | 954 } |
955 #endif | 955 #endif |
956 | 956 |
957 /* Create process */ | 957 /* Create process */ |
958 { | 958 { |
959 STARTUPINFOW si; | 959 STARTUPINFOW si; |
960 PROCESS_INFORMATION pi; | 960 PROCESS_INFORMATION pi; |
961 DWORD err; | 961 DWORD err; |
1002 /* These just have been inherited; we do not need a copy */ | 1002 /* These just have been inherited; we do not need a copy */ |
1003 CloseHandle (hprocin); | 1003 CloseHandle (hprocin); |
1004 CloseHandle (hprocout); | 1004 CloseHandle (hprocout); |
1005 CloseHandle (hprocerr); | 1005 CloseHandle (hprocerr); |
1006 } | 1006 } |
1007 | 1007 |
1008 /* Handle process creation failure */ | 1008 /* Handle process creation failure */ |
1009 if (err) | 1009 if (err) |
1010 { | 1010 { |
1011 if (do_io) | 1011 if (do_io) |
1012 { | 1012 { |
1044 | 1044 |
1045 return ((int)pi.dwProcessId); | 1045 return ((int)pi.dwProcessId); |
1046 } | 1046 } |
1047 } | 1047 } |
1048 | 1048 |
1049 /* | 1049 /* |
1050 * This method is called to update status fields of the process | 1050 * This method is called to update status fields of the process |
1051 * structure. If the process has not existed, this method is expected | 1051 * structure. If the process has not existed, this method is expected |
1052 * to do nothing. | 1052 * to do nothing. |
1053 * | 1053 * |
1054 * The method is called only for real child processes. | 1054 * The method is called only for real child processes. |
1055 */ | 1055 */ |
1056 | 1056 |
1057 static void | 1057 static void |
1058 nt_update_status_if_terminated (Lisp_Process *p) | 1058 nt_update_status_if_terminated (Lisp_Process *p) |
1059 { | 1059 { |
1343 /* We don't want to be blocked on connect */ | 1343 /* We don't want to be blocked on connect */ |
1344 { | 1344 { |
1345 unsigned long nonblock = 1; | 1345 unsigned long nonblock = 1; |
1346 ioctlsocket (s, FIONBIO, &nonblock); | 1346 ioctlsocket (s, FIONBIO, &nonblock); |
1347 } | 1347 } |
1348 | 1348 |
1349 retval = connect (s, (struct sockaddr *) &address, sizeof (address)); | 1349 retval = connect (s, (struct sockaddr *) &address, sizeof (address)); |
1350 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) | 1350 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) |
1351 { | 1351 { |
1352 errnum = WSAGetLastError (); | 1352 errnum = WSAGetLastError (); |
1353 goto connect_failed; | 1353 goto connect_failed; |