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 */