diff options
| author | Geoff Voelker | 1998-04-17 05:10:29 +0000 |
|---|---|---|
| committer | Geoff Voelker | 1998-04-17 05:10:29 +0000 |
| commit | ef79fbba2fb79df89a0ec9476981e7eb996d4f7d (patch) | |
| tree | 5d677036fba60360d80eed8a572a91749e425f2a /src/w32proc.c | |
| parent | c88696553221c2e8df18c16b64d7f9e405128d2b (diff) | |
| download | emacs-ef79fbba2fb79df89a0ec9476981e7eb996d4f7d.tar.gz emacs-ef79fbba2fb79df89a0ec9476981e7eb996d4f7d.zip | |
(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.
Diffstat (limited to 'src/w32proc.c')
| -rw-r--r-- | src/w32proc.c | 108 |
1 files changed, 100 insertions, 8 deletions
diff --git a/src/w32proc.c b/src/w32proc.c index f01b34daa55..1acae25a9f5 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA. | |||
| 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 |
| @@ -606,7 +607,7 @@ w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app) | |||
| 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; |
| @@ -736,7 +737,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 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 |
| @@ -771,7 +772,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 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 |
| @@ -1109,8 +1110,17 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, | |||
| 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 | } |
| @@ -1119,8 +1129,14 @@ 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; |
| @@ -1176,9 +1192,16 @@ count_children: | |||
| 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", |
| @@ -1314,6 +1337,10 @@ sys_kill (int pid, int sig) | |||
| 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 | } |
| @@ -1349,7 +1376,24 @@ sys_kill (int pid, int sig) | |||
| 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 |
| @@ -1696,6 +1740,48 @@ human-readable form.") | |||
| 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\ |
| @@ -1726,6 +1812,11 @@ If successful, the new locale id is returned, otherwise nil.") | |||
| 1726 | if (!SetThreadLocale (XINT (lcid))) | 1812 | if (!SetThreadLocale (XINT (lcid))) |
| 1727 | return Qnil; | 1813 | return Qnil; |
| 1728 | 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); | ||
| 1819 | |||
| 1729 | return make_number (GetThreadLocale ()); | 1820 | return make_number (GetThreadLocale ()); |
| 1730 | } | 1821 | } |
| 1731 | 1822 | ||
| @@ -1745,6 +1836,7 @@ syms_of_ntproc () | |||
| 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, |