Mercurial > hg > xemacs-beta
comparison src/process-nt.c @ 410:de805c49cfc1 r21-2-35
Import from CVS: tag r21-2-35
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:19:21 +0200 |
parents | 501cfd01ee6d |
children | 697ef44129c6 |
comparison
equal
deleted
inserted
replaced
409:301b9ebbdf3b | 410:de805c49cfc1 |
---|---|
34 #include "process.h" | 34 #include "process.h" |
35 #include "procimpl.h" | 35 #include "procimpl.h" |
36 #include "sysdep.h" | 36 #include "sysdep.h" |
37 | 37 |
38 #include <shellapi.h> | 38 #include <shellapi.h> |
39 #ifdef __MINGW32__ | |
40 #include <errno.h> | 39 #include <errno.h> |
41 #endif | |
42 #include <signal.h> | 40 #include <signal.h> |
43 #ifdef HAVE_SOCKETS | 41 #ifdef HAVE_SOCKETS |
44 #include <winsock.h> | 42 #include <winsock.h> |
45 #endif | 43 #endif |
46 | 44 |
51 struct nt_process_data | 49 struct nt_process_data |
52 { | 50 { |
53 HANDLE h_process; | 51 HANDLE h_process; |
54 DWORD dwProcessId; | 52 DWORD dwProcessId; |
55 HWND hwnd; /* console window */ | 53 HWND hwnd; /* console window */ |
56 int need_enable_child_signals; | |
57 }; | 54 }; |
58 | 55 |
59 /* Control how args are quoted to ensure correct parsing by child | 56 /* Control how args are quoted to ensure correct parsing by child |
60 process. */ | 57 process. */ |
61 Lisp_Object Vmswindows_quote_process_args; | 58 Lisp_Object Vmswindows_quote_process_args; |
420 { | 417 { |
421 char window_class[32]; | 418 char window_class[32]; |
422 | 419 |
423 GetClassName (hwnd, window_class, sizeof (window_class)); | 420 GetClassName (hwnd, window_class, sizeof (window_class)); |
424 if (strcmp (window_class, | 421 if (strcmp (window_class, |
425 msw_windows9x_p () | 422 mswindows_windows9x_p () |
426 ? "tty" | 423 ? "tty" |
427 : "ConsoleWindowClass") == 0) | 424 : "ConsoleWindowClass") == 0) |
428 { | 425 { |
429 cp->hwnd = hwnd; | 426 cp->hwnd = hwnd; |
430 return FALSE; | 427 return FALSE; |
541 else | 538 else |
542 { | 539 { |
543 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd) | 540 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd) |
544 { | 541 { |
545 #if 1 | 542 #if 1 |
546 if (msw_windows9x_p ()) | 543 if (mswindows_windows9x_p ()) |
547 { | 544 { |
548 /* | 545 /* |
549 Another possibility is to try terminating the VDM out-right by | 546 Another possibility is to try terminating the VDM out-right by |
550 calling the Shell VxD (id 0x17) V86 interface, function #4 | 547 calling the Shell VxD (id 0x17) V86 interface, function #4 |
551 "SHELL_Destroy_VM", ie. | 548 "SHELL_Destroy_VM", ie. |
679 } | 676 } |
680 | 677 |
681 static void | 678 static void |
682 ensure_console_window_exists (void) | 679 ensure_console_window_exists (void) |
683 { | 680 { |
684 if (msw_windows9x_p ()) | 681 if (mswindows_windows9x_p ()) |
685 msw_hide_console (); | 682 mswindows_hide_console (); |
686 } | 683 } |
687 | 684 |
688 int | 685 int |
689 compare_env (const void *strp1, const void *strp2) | 686 compare_env (const void *strp1, const void *strp2) |
690 { | 687 { |
768 CreatePipe (&hprocin, &hmyshove, &sa, 0); | 765 CreatePipe (&hprocin, &hmyshove, &sa, 0); |
769 CreatePipe (&hmyslurp, &hprocout, &sa, 0); | 766 CreatePipe (&hmyslurp, &hprocout, &sa, 0); |
770 | 767 |
771 /* Duplicate the stdout handle for use as stderr */ | 768 /* Duplicate the stdout handle for use as stderr */ |
772 DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(), | 769 DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(), |
773 &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS); | 770 &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS); |
774 | 771 |
775 /* Stupid Win32 allows to create a pipe with *both* ends either | 772 /* Stupid Win32 allows to create a pipe with *both* ends either |
776 inheritable or not. We need process ends inheritable, and local | 773 inheritable or not. We need process ends inheritable, and local |
777 ends not inheritable. */ | 774 ends not inheritable. */ |
778 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), | 775 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), |
788 /* Convert an argv vector into Win32 style command line. */ | 785 /* Convert an argv vector into Win32 style command line. */ |
789 { | 786 { |
790 int i; | 787 int i; |
791 Bufbyte **quoted_args; | 788 Bufbyte **quoted_args; |
792 int is_dos_app, is_cygnus_app; | 789 int is_dos_app, is_cygnus_app; |
790 int is_command_shell; | |
793 int do_quoting = 0; | 791 int do_quoting = 0; |
794 char escape_char = 0; | 792 char escape_char = 0; |
795 | 793 |
796 nargv++; /* include program; we access argv offset by 1 below */ | 794 nargv++; /* include program; we access argv offset by 1 below */ |
797 quoted_args = alloca_array (Bufbyte *, nargv); | 795 quoted_args = alloca_array (Bufbyte *, nargv); |
802 cygwin.dll to parse the command line - we use this to decide how to | 800 cygwin.dll to parse the command line - we use this to decide how to |
803 escape quote chars in command line args that must be quoted). */ | 801 escape quote chars in command line args that must be quoted). */ |
804 mswindows_executable_type (XSTRING_DATA (program), | 802 mswindows_executable_type (XSTRING_DATA (program), |
805 &is_dos_app, &is_cygnus_app); | 803 &is_dos_app, &is_cygnus_app); |
806 | 804 |
805 { | |
806 /* #### Bleeeeeeeeeeeeeeeeech!!!! The command shells appear to | |
807 use '^' as a quote character, at least under NT. #### I haven't | |
808 tested 95. If it allows no quoting conventions at all, set | |
809 escape_char to 0 and the code below will work. (e.g. NT tolerates | |
810 no quoting -- this command | |
811 | |
812 cmd /c "ls "/Program Files"" | |
813 | |
814 actually works.) */ | |
815 | |
816 struct gcpro gcpro1, gcpro2; | |
817 Lisp_Object progname = Qnil; | |
818 | |
819 GCPRO2 (program, progname); | |
820 progname = Ffile_name_nondirectory (program); | |
821 progname = Fdowncase (progname, Qnil); | |
822 | |
823 is_command_shell = | |
824 internal_equal (progname, build_string ("command.com"), 0) | |
825 || internal_equal (progname, build_string ("cmd.exe"), 0); | |
826 UNGCPRO; | |
827 } | |
828 | |
807 #if 0 | 829 #if 0 |
808 /* #### we need to port this. */ | 830 /* #### we need to port this. */ |
809 /* On Windows 95, if cmdname is a DOS app, we invoke a helper | 831 /* On Windows 95, if cmdname is a DOS app, we invoke a helper |
810 application to start it by specifying the helper app as cmdname, | 832 application to start it by specifying the helper app as cmdname, |
811 while leaving the real app name as argv[0]. */ | 833 while leaving the real app name as argv[0]. */ |
858 /* Override escape char by binding mswindows-quote-process-args to | 880 /* Override escape char by binding mswindows-quote-process-args to |
859 desired character, or use t for auto-selection. */ | 881 desired character, or use t for auto-selection. */ |
860 if (INTP (Vmswindows_quote_process_args)) | 882 if (INTP (Vmswindows_quote_process_args)) |
861 escape_char = (char) XINT (Vmswindows_quote_process_args); | 883 escape_char = (char) XINT (Vmswindows_quote_process_args); |
862 else | 884 else |
863 escape_char = is_cygnus_app ? '"' : '\\'; | 885 escape_char = is_command_shell ? '^' : is_cygnus_app ? '"' : '\\'; |
864 } | 886 } |
865 | 887 |
866 /* do argv... */ | 888 /* do argv... */ |
867 for (i = 0; i < nargv; ++i) | 889 for (i = 0; i < nargv; ++i) |
868 { | 890 { |
877 for ( ; *p; p++) | 899 for ( ; *p; p++) |
878 { | 900 { |
879 if (*p == '"') | 901 if (*p == '"') |
880 { | 902 { |
881 /* allow for embedded quotes to be escaped */ | 903 /* allow for embedded quotes to be escaped */ |
882 arglen++; | 904 if (escape_char) |
905 arglen++; | |
883 need_quotes = 1; | 906 need_quotes = 1; |
884 /* handle the case where the embedded quote is already escaped */ | 907 /* handle the case where the embedded quote is already escaped */ |
885 if (escape_char_run > 0) | 908 if (escape_char_run > 0) |
886 { | 909 { |
887 /* To preserve the arg exactly, we need to double the | 910 /* To preserve the arg exactly, we need to double the |
893 else if (*p == ' ' || *p == '\t') | 916 else if (*p == ' ' || *p == '\t') |
894 { | 917 { |
895 need_quotes = 1; | 918 need_quotes = 1; |
896 } | 919 } |
897 | 920 |
898 if (*p == escape_char && escape_char != '"') | 921 if (escape_char && *p == escape_char && escape_char != '"') |
899 escape_char_run++; | 922 escape_char_run++; |
900 else | 923 else |
901 escape_char_run = 0; | 924 escape_char_run = 0; |
902 } | 925 } |
903 if (need_quotes) | 926 if (need_quotes) |
953 *parg++ = *p++; | 976 *parg++ = *p++; |
954 } | 977 } |
955 #else | 978 #else |
956 for ( ; *p; p++) | 979 for ( ; *p; p++) |
957 { | 980 { |
958 if (*p == '"') | 981 if (escape_char && *p == '"') |
959 { | 982 { |
960 /* double preceding escape chars if any */ | 983 /* double preceding escape chars if any */ |
961 while (escape_char_run > 0) | 984 while (escape_char_run > 0) |
962 { | 985 { |
963 *parg++ = escape_char; | 986 *parg++ = escape_char; |
966 /* escape all quote chars, even at beginning or end */ | 989 /* escape all quote chars, even at beginning or end */ |
967 *parg++ = escape_char; | 990 *parg++ = escape_char; |
968 } | 991 } |
969 *parg++ = *p; | 992 *parg++ = *p; |
970 | 993 |
971 if (*p == escape_char && escape_char != '"') | 994 if (escape_char && *p == escape_char && escape_char != '"') |
972 escape_char_run++; | 995 escape_char_run++; |
973 else | 996 else |
974 escape_char_run = 0; | 997 escape_char_run = 0; |
975 } | 998 } |
976 /* double escape chars before enclosing quote */ | 999 /* double escape chars before enclosing quote */ |
1118 si.hStdError = hprocerr; | 1141 si.hStdError = hprocerr; |
1119 si.dwFlags |= STARTF_USESTDHANDLES; | 1142 si.dwFlags |= STARTF_USESTDHANDLES; |
1120 } | 1143 } |
1121 | 1144 |
1122 flags = CREATE_SUSPENDED; | 1145 flags = CREATE_SUSPENDED; |
1123 if (msw_windows9x_p ()) | 1146 if (mswindows_windows9x_p ()) |
1124 flags |= (!NILP (Vmswindows_start_process_share_console) | 1147 flags |= (!NILP (Vmswindows_start_process_share_console) |
1125 ? CREATE_NEW_PROCESS_GROUP | 1148 ? CREATE_NEW_PROCESS_GROUP |
1126 : CREATE_NEW_CONSOLE); | 1149 : CREATE_NEW_CONSOLE); |
1127 else | 1150 else |
1128 flags |= CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP; | 1151 flags |= CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP; |
1166 /* Indicate as if the process has exited immediately. */ | 1189 /* Indicate as if the process has exited immediately. */ |
1167 p->status_symbol = Qexit; | 1190 p->status_symbol = Qexit; |
1168 CloseHandle (pi.hProcess); | 1191 CloseHandle (pi.hProcess); |
1169 } | 1192 } |
1170 | 1193 |
1194 if (!windowed) | |
1195 enable_child_signals (pi.hProcess); | |
1196 | |
1171 ResumeThread (pi.hThread); | 1197 ResumeThread (pi.hThread); |
1172 CloseHandle (pi.hThread); | 1198 CloseHandle (pi.hThread); |
1173 | |
1174 /* Remember to enable child signals later if this is not a windowed | |
1175 app. Can't do it right now because that screws up the MKS Toolkit | |
1176 shell. */ | |
1177 if (!windowed) | |
1178 { | |
1179 NT_DATA(p)->need_enable_child_signals = 10; | |
1180 kick_status_notify (); | |
1181 } | |
1182 | 1199 |
1183 return ((int)pi.dwProcessId); | 1200 return ((int)pi.dwProcessId); |
1184 } | 1201 } |
1185 } | 1202 } |
1186 | 1203 |
1194 | 1211 |
1195 static void | 1212 static void |
1196 nt_update_status_if_terminated (Lisp_Process* p) | 1213 nt_update_status_if_terminated (Lisp_Process* p) |
1197 { | 1214 { |
1198 DWORD exit_code; | 1215 DWORD exit_code; |
1199 | |
1200 if (NT_DATA(p)->need_enable_child_signals > 1) | |
1201 { | |
1202 NT_DATA(p)->need_enable_child_signals -= 1; | |
1203 kick_status_notify (); | |
1204 } | |
1205 else if (NT_DATA(p)->need_enable_child_signals == 1) | |
1206 { | |
1207 enable_child_signals(NT_DATA(p)->h_process); | |
1208 NT_DATA(p)->need_enable_child_signals = 0; | |
1209 } | |
1210 | |
1211 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code) | 1216 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code) |
1212 && exit_code != STILL_ACTIVE) | 1217 && exit_code != STILL_ACTIVE) |
1213 { | 1218 { |
1214 p->tick++; | 1219 p->tick++; |
1215 p->core_dumped = 0; | 1220 p->core_dumped = 0; |
1307 static void | 1312 static void |
1308 nt_kill_child_process (Lisp_Object proc, int signo, | 1313 nt_kill_child_process (Lisp_Object proc, int signo, |
1309 int current_group, int nomsg) | 1314 int current_group, int nomsg) |
1310 { | 1315 { |
1311 Lisp_Process *p = XPROCESS (proc); | 1316 Lisp_Process *p = XPROCESS (proc); |
1312 | |
1313 /* Enable child signals if necessary. This may lose the first | |
1314 but it's better than nothing. */ | |
1315 if (NT_DATA (p)->need_enable_child_signals > 0) | |
1316 { | |
1317 enable_child_signals (NT_DATA(p)->h_process); | |
1318 NT_DATA (p)->need_enable_child_signals = 0; | |
1319 } | |
1320 | 1317 |
1321 /* Signal error if SIGNO cannot be sent */ | 1318 /* Signal error if SIGNO cannot be sent */ |
1322 validate_signal_number (signo); | 1319 validate_signal_number (signo); |
1323 | 1320 |
1324 /* Send signal */ | 1321 /* Send signal */ |