comparison src/w32proc.c @ 21613:fe4f5bfae371

(w32_executable_type): Properly cast dos_header when making size comparison. (sys_spawnve): Update comments. (sys_select): Ignore children dead children with pending input. Delay sending SIGCHLD until all output has been read. (sys_kill): Sleep to allow focus change events to propagate. Use TerminateProcess on Win95. (int_from_hex, enum_locale_fn, Fw32_get_valid_locale_ids): New functions. (Vw32_valid_locale_ids): New variable. (Fw32_set_current_locale): Send message to input thread. (syms_of_ntproc): defsubr Sw32_get_valid_locale_ids.
author Geoff Voelker <voelker@cs.washington.edu>
date Fri, 17 Apr 1998 05:10:29 +0000
parents bd9b548fd162
children b1c3fe58dbbe
comparison
equal deleted inserted replaced
21612:24a01af0cd38 21613:fe4f5bfae371
43 #include "w32.h" 43 #include "w32.h"
44 #include "w32heap.h" 44 #include "w32heap.h"
45 #include "systime.h" 45 #include "systime.h"
46 #include "syswait.h" 46 #include "syswait.h"
47 #include "process.h" 47 #include "process.h"
48 #include "w32term.h"
48 49
49 /* Control whether spawnve quotes arguments as necessary to ensure 50 /* Control whether spawnve quotes arguments as necessary to ensure
50 correct parsing by child process. Because not all uses of spawnve 51 correct parsing by child process. Because not all uses of spawnve
51 are careful about constructing argv arrays, we make this behaviour 52 are careful about constructing argv arrays, we make this behaviour
52 conditional (off by default). */ 53 conditional (off by default). */
604 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 605 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
605 goto unwind; 606 goto unwind;
606 607
607 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew); 608 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
608 609
609 if (nt_header > dos_header + executable.size) 610 if ((char *) nt_header > (char *) dos_header + executable.size)
610 { 611 {
611 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ 612 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
612 *is_dos_app = TRUE; 613 *is_dos_app = TRUE;
613 } 614 }
614 else if (nt_header->Signature != IMAGE_NT_SIGNATURE 615 else if (nt_header->Signature != IMAGE_NT_SIGNATURE
734 /* make sure argv[0] and cmdname are both in DOS format */ 735 /* make sure argv[0] and cmdname are both in DOS format */
735 cmdname = XSTRING (program)->data; 736 cmdname = XSTRING (program)->data;
736 unixtodos_filename (cmdname); 737 unixtodos_filename (cmdname);
737 argv[0] = cmdname; 738 argv[0] = cmdname;
738 739
739 /* Determine whether program is a 16-bit DOS executable, or a Win32 740 /* Determine whether program is a 16-bit DOS executable, or a w32
740 executable that is implicitly linked to the Cygnus dll (implying it 741 executable that is implicitly linked to the Cygnus dll (implying it
741 was compiled with the Cygnus GNU toolchain and hence relies on 742 was compiled with the Cygnus GNU toolchain and hence relies on
742 cygwin.dll to parse the command line - we use this to decide how to 743 cygwin.dll to parse the command line - we use this to decide how to
743 escape quote chars in command line args that must be quoted). */ 744 escape quote chars in command line args that must be quoted). */
744 w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app); 745 w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
769 embedded quotes need to be escaped as well. The aim is to ensure 770 embedded quotes need to be escaped as well. The aim is to ensure
770 the child process reconstructs the argv array we start with 771 the child process reconstructs the argv array we start with
771 exactly, so we treat quotes at the beginning and end of arguments 772 exactly, so we treat quotes at the beginning and end of arguments
772 as embedded quotes. 773 as embedded quotes.
773 774
774 The Win32 GNU-based library from Cygnus doubles quotes to escape 775 The w32 GNU-based library from Cygnus doubles quotes to escape
775 them, while MSVC uses backslash for escaping. (Actually the MSVC 776 them, while MSVC uses backslash for escaping. (Actually the MSVC
776 startup code does attempt to recognise doubled quotes and accept 777 startup code does attempt to recognise doubled quotes and accept
777 them, but gets it wrong and ends up requiring three quotes to get a 778 them, but gets it wrong and ends up requiring three quotes to get a
778 single embedded quote!) So by default we decide whether to use 779 single embedded quote!) So by default we decide whether to use
779 quote or backslash as the escape character based on whether the 780 quote or backslash as the escape character based on whether the
1107 #endif 1108 #endif
1108 } 1109 }
1109 else 1110 else
1110 { 1111 {
1111 /* Unable to find something to wait on for this fd, skip */ 1112 /* Unable to find something to wait on for this fd, skip */
1113
1114 /* Note that this is not a fatal error, and can in fact
1115 happen in unusual circumstances. Specifically, if
1116 sys_spawnve fails, eg. because the program doesn't
1117 exist, and debug-on-error is t so Fsignal invokes a
1118 nested input loop, then the process output pipe is
1119 still included in input_wait_mask with no child_proc
1120 associated with it. (It is removed when the debugger
1121 exits the nested input loop and the error is thrown.) */
1122
1112 DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i)); 1123 DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i));
1113 abort ();
1114 } 1124 }
1115 } 1125 }
1116 } 1126 }
1117 1127
1118 count_children: 1128 count_children:
1119 /* Add handles of child processes. */ 1129 /* Add handles of child processes. */
1120 nc = 0; 1130 nc = 0;
1121 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) 1131 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
1122 /* some child_procs might be sockets; ignore them */ 1132 /* Some child_procs might be sockets; ignore them. Also some
1123 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess) 1133 children may have died already, but we haven't finished reading
1134 the process output; ignore them too. */
1135 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
1136 && (cp->fd < 0
1137 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0
1138 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
1139 )
1124 { 1140 {
1125 wait_hnd[nh + nc] = cp->procinfo.hProcess; 1141 wait_hnd[nh + nc] = cp->procinfo.hProcess;
1126 cps[nc] = cp; 1142 cps[nc] = cp;
1127 nc++; 1143 nc++;
1128 } 1144 }
1174 do 1190 do
1175 { 1191 {
1176 if (active >= nh) 1192 if (active >= nh)
1177 { 1193 {
1178 cp = cps[active - nh]; 1194 cp = cps[active - nh];
1195
1196 /* We cannot always signal SIGCHLD immediately; if we have not
1197 finished reading the process output, we must delay sending
1198 SIGCHLD until we do. */
1199
1200 if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0)
1201 fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD;
1179 /* SIG_DFL for SIGCHLD is ignore */ 1202 /* SIG_DFL for SIGCHLD is ignore */
1180 if (sig_handlers[SIGCHLD] != SIG_DFL 1203 else if (sig_handlers[SIGCHLD] != SIG_DFL &&
1181 && sig_handlers[SIGCHLD] != SIG_IGN) 1204 sig_handlers[SIGCHLD] != SIG_IGN)
1182 { 1205 {
1183 #ifdef FULL_DEBUG 1206 #ifdef FULL_DEBUG
1184 DebPrint (("select calling SIGCHLD handler for pid %d\n", 1207 DebPrint (("select calling SIGCHLD handler for pid %d\n",
1185 cp->pid)); 1208 cp->pid));
1186 #endif 1209 #endif
1312 keybd_event (VK_CONTROL, control_scan_code, 0, 0); 1335 keybd_event (VK_CONTROL, control_scan_code, 0, 0);
1313 keybd_event (vk_break_code, break_scan_code, 0, 0); 1336 keybd_event (vk_break_code, break_scan_code, 0, 0);
1314 keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0); 1337 keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0);
1315 keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0); 1338 keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
1316 1339
1340 /* Sleep for a bit to give time for Emacs frame to respond
1341 to focus change events (if Emacs was active app). */
1342 Sleep (10);
1343
1317 SetForegroundWindow (foreground_window); 1344 SetForegroundWindow (foreground_window);
1318 } 1345 }
1319 } 1346 }
1320 /* Ctrl-Break is NT equivalent of SIGINT. */ 1347 /* Ctrl-Break is NT equivalent of SIGINT. */
1321 else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid)) 1348 else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
1347 Switch_VM_and_callback). 1374 Switch_VM_and_callback).
1348 1375
1349 Could try to invoke DestroyVM through CallVxD. 1376 Could try to invoke DestroyVM through CallVxD.
1350 1377
1351 */ 1378 */
1379 #if 0
1380 /* On Win95, posting WM_QUIT causes the 16-bit subsystem
1381 to hang when cmdproxy is used in conjunction with
1382 command.com for an interactive shell. Posting
1383 WM_CLOSE pops up a dialog that, when Yes is selected,
1384 does the same thing. TerminateProcess is also less
1385 than ideal in that subprocesses tend to stick around
1386 until the machine is shutdown, but at least it
1387 doesn't freeze the 16-bit subsystem. */
1352 PostMessage (cp->hwnd, WM_QUIT, 0xff, 0); 1388 PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
1389 #endif
1390 if (!TerminateProcess (proc_hand, 0xff))
1391 {
1392 DebPrint (("sys_kill.TerminateProcess returned %d "
1393 "for pid %lu\n", GetLastError (), pid));
1394 errno = EINVAL;
1395 rc = -1;
1396 }
1353 } 1397 }
1354 else 1398 else
1355 #endif 1399 #endif
1356 PostMessage (cp->hwnd, WM_CLOSE, 0, 0); 1400 PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
1357 } 1401 }
1694 () 1738 ()
1695 { 1739 {
1696 return make_number (GetThreadLocale ()); 1740 return make_number (GetThreadLocale ());
1697 } 1741 }
1698 1742
1743 DWORD int_from_hex (char * s)
1744 {
1745 DWORD val = 0;
1746 static char hex[] = "0123456789abcdefABCDEF";
1747 char * p;
1748
1749 while (*s && (p = strchr(hex, *s)) != NULL)
1750 {
1751 unsigned digit = p - hex;
1752 if (digit > 15)
1753 digit -= 6;
1754 val = val * 16 + digit;
1755 s++;
1756 }
1757 return val;
1758 }
1759
1760 /* We need to build a global list, since the EnumSystemLocale callback
1761 function isn't given a context pointer. */
1762 Lisp_Object Vw32_valid_locale_ids;
1763
1764 BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
1765 {
1766 DWORD id = int_from_hex (localeNum);
1767 Vw32_valid_locale_ids = Fcons (make_number (id), Vw32_valid_locale_ids);
1768 return TRUE;
1769 }
1770
1771 DEFUN ("w32-get-valid-locale-ids", Fw32_get_valid_locale_ids, Sw32_get_valid_locale_ids, 0, 0, 0,
1772 "Return list of all valid Windows locale ids.\n\
1773 Each id is a numerical value; use `w32-get-locale-info' to convert to a\n\
1774 human-readable form.")
1775 ()
1776 {
1777 Vw32_valid_locale_ids = Qnil;
1778
1779 EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED);
1780
1781 Vw32_valid_locale_ids = Fnreverse (Vw32_valid_locale_ids);
1782 return Vw32_valid_locale_ids;
1783 }
1784
1699 1785
1700 DEFUN ("w32-get-default-locale-id", Fw32_get_default_locale_id, Sw32_get_default_locale_id, 0, 1, 0, 1786 DEFUN ("w32-get-default-locale-id", Fw32_get_default_locale_id, Sw32_get_default_locale_id, 0, 1, 0,
1701 "Return Windows locale id for default locale setting.\n\ 1787 "Return Windows locale id for default locale setting.\n\
1702 By default, the system default locale setting is returned; if the optional\n\ 1788 By default, the system default locale setting is returned; if the optional\n\
1703 parameter USERP is non-nil, the user default locale setting is returned.\n\ 1789 parameter USERP is non-nil, the user default locale setting is returned.\n\
1723 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED)) 1809 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1724 return Qnil; 1810 return Qnil;
1725 1811
1726 if (!SetThreadLocale (XINT (lcid))) 1812 if (!SetThreadLocale (XINT (lcid)))
1727 return Qnil; 1813 return Qnil;
1814
1815 /* Need to set input thread locale if present. */
1816 if (dwWindowsThreadId)
1817 /* Reply is not needed. */
1818 PostThreadMessage (dwWindowsThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0);
1728 1819
1729 return make_number (GetThreadLocale ()); 1820 return make_number (GetThreadLocale ());
1730 } 1821 }
1731 1822
1732 1823
1743 defsubr (&Sw32_long_file_name); 1834 defsubr (&Sw32_long_file_name);
1744 defsubr (&Sw32_set_process_priority); 1835 defsubr (&Sw32_set_process_priority);
1745 defsubr (&Sw32_get_locale_info); 1836 defsubr (&Sw32_get_locale_info);
1746 defsubr (&Sw32_get_current_locale_id); 1837 defsubr (&Sw32_get_current_locale_id);
1747 defsubr (&Sw32_get_default_locale_id); 1838 defsubr (&Sw32_get_default_locale_id);
1839 defsubr (&Sw32_get_valid_locale_ids);
1748 defsubr (&Sw32_set_current_locale); 1840 defsubr (&Sw32_set_current_locale);
1749 1841
1750 DEFVAR_LISP ("w32-quote-process-args", &Vw32_quote_process_args, 1842 DEFVAR_LISP ("w32-quote-process-args", &Vw32_quote_process_args,
1751 "Non-nil enables quoting of process arguments to ensure correct parsing.\n\ 1843 "Non-nil enables quoting of process arguments to ensure correct parsing.\n\
1752 Because Windows does not directly pass argv arrays to child processes,\n\ 1844 Because Windows does not directly pass argv arrays to child processes,\n\