/* Process support for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1992, 1995, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
Drew Bliss Oct 14, 1993
Adapted from alarm.c by Tim Fleehart
extern BOOL WINAPI IsValidLocale(LCID, DWORD);
#endif
+#ifdef HAVE_LANGINFO_CODESET
+#include <nl_types.h>
+#include <langinfo.h>
+#endif
+
#include "lisp.h"
#include "w32.h"
#include "w32heap.h"
#include "syssignal.h"
#include "w32term.h"
+#define RVA_TO_PTR(var,section,filedata) \
+ ((void *)((section)->PointerToRawData \
+ + ((DWORD)(var) - (section)->VirtualAddress) \
+ + (filedata).file_base))
+
/* Control whether spawnve quotes arguments as necessary to ensure
correct parsing by child process. Because not all uses of spawnve
are careful about constructing argv arrays, we make this behaviour
avoids the inefficiency of frequently reading small amounts of data.
This is primarily necessary for handling DOS processes on Windows 95,
but is useful for W32 processes on both Windows 95 and NT as well. */
-Lisp_Object Vw32_pipe_read_delay;
+int w32_pipe_read_delay;
/* Control conversion of upper case file names to lower case.
nil means no, t means yes. */
/* let the thread exit cleanly if possible */
cp->status = STATUS_READ_ERROR;
SetEvent (cp->char_consumed);
+#if 0
+ /* We used to forceably terminate the thread here, but it
+ is normally unnecessary, and in abnormal cases, the worst that
+ will happen is we have an extra idle thread hanging around
+ waiting for the zombie process. */
if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0)
{
DebPrint (("delete_child.WaitForSingleObject (thread) failed "
"with %lu for fd %ld\n", GetLastError (), cp->fd));
TerminateThread (cp->thrd, 0);
}
+#endif
}
CloseHandle (cp->thrd);
cp->thrd = NULL;
{
int rc;
- rc = _sys_read_ahead (cp->fd);
+ if (fd_info[cp->fd].flags & FILE_LISTEN)
+ rc = _sys_wait_accept (cp->fd);
+ else
+ rc = _sys_read_ahead (cp->fd);
/* The name char_avail is a misnomer - it really just means the
read-ahead has completed, whether successfully or not. */
cp->pid = -cp->pid;
/* pid must fit in a Lisp_Int */
- cp->pid = (cp->pid & VALMASK);
+ cp->pid = cp->pid & INTMASK;
*pPid = cp->pid;
{
for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
/* some child_procs might be sockets; ignore them */
- if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
+ if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
+ && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
{
wait_hnd[nh] = cp->procinfo.hProcess;
cps[nh] = cp;
return pid;
}
+/* Old versions of w32api headers don't have separate 32-bit and
+ 64-bit defines, but the one they have matches the 32-bit variety. */
+#ifndef IMAGE_NT_OPTIONAL_HDR32_MAGIC
+# define IMAGE_NT_OPTIONAL_HDR32_MAGIC IMAGE_NT_OPTIONAL_HDR_MAGIC
+# define IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER
+#endif
+
void
w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int * is_gui_app)
{
}
else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
{
- /* Look for cygwin.dll in DLL import list. */
- IMAGE_DATA_DIRECTORY import_dir =
- nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
- IMAGE_IMPORT_DESCRIPTOR * imports;
- IMAGE_SECTION_HEADER * section;
-
- section = rva_to_section (import_dir.VirtualAddress, nt_header);
- imports = RVA_TO_PTR (import_dir.VirtualAddress, section, executable);
-
- for ( ; imports->Name; imports++)
- {
- char * dllname = RVA_TO_PTR (imports->Name, section, executable);
-
- /* The exact name of the cygwin dll has changed with
- various releases, but hopefully this will be reasonably
- future proof. */
- if (strncmp (dllname, "cygwin", 6) == 0)
- {
- *is_cygnus_app = TRUE;
- break;
- }
- }
-
- /* Check whether app is marked as a console or windowed (aka
- GUI) app. Accept Posix and OS2 subsytem apps as console
- apps. */
- *is_gui_app = (nt_header->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI);
+ IMAGE_DATA_DIRECTORY *data_dir = NULL;
+ if (nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ {
+ /* Ensure we are using the 32 bit structure. */
+ IMAGE_OPTIONAL_HEADER32 *opt
+ = (IMAGE_OPTIONAL_HEADER32*) &(nt_header->OptionalHeader);
+ data_dir = opt->DataDirectory;
+ *is_gui_app = (opt->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI);
+ }
+ /* MingW 3.12 has the required 64 bit structs, but in case older
+ versions don't, only check 64 bit exes if we know how. */
+#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC
+ else if (nt_header->OptionalHeader.Magic
+ == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ IMAGE_OPTIONAL_HEADER64 *opt
+ = (IMAGE_OPTIONAL_HEADER64*) &(nt_header->OptionalHeader);
+ data_dir = opt->DataDirectory;
+ *is_gui_app = (opt->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI);
+ }
+#endif
+ if (data_dir)
+ {
+ /* Look for cygwin.dll in DLL import list. */
+ IMAGE_DATA_DIRECTORY import_dir =
+ data_dir[IMAGE_DIRECTORY_ENTRY_IMPORT];
+ IMAGE_IMPORT_DESCRIPTOR * imports;
+ IMAGE_SECTION_HEADER * section;
+
+ section = rva_to_section (import_dir.VirtualAddress, nt_header);
+ imports = RVA_TO_PTR (import_dir.VirtualAddress, section,
+ executable);
+
+ for ( ; imports->Name; imports++)
+ {
+ char * dllname = RVA_TO_PTR (imports->Name, section,
+ executable);
+
+ /* The exact name of the cygwin dll has changed with
+ various releases, but hopefully this will be reasonably
+ future proof. */
+ if (strncmp (dllname, "cygwin", 6) == 0)
+ {
+ *is_cygnus_app = TRUE;
+ break;
+ }
+ }
+ }
}
}
{
DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
nh + nc, timeout_ms, GetLastError ()));
- /* don't return EBADF - this causes wait_reading_process_input to
+ /* don't return EBADF - this causes wait_reading_process_output to
abort; WAIT_FAILED is returned when single-stepping under
Windows 95 after switching thread focus in debugger, and
possibly at other times. */
return result;
}
+#ifdef HAVE_LANGINFO_CODESET
+/* Emulation of nl_langinfo. Used in fns.c:Flocale_info. */
+char *nl_langinfo (nl_item item)
+{
+ /* Conversion of Posix item numbers to their Windows equivalents. */
+ static const LCTYPE w32item[] = {
+ LOCALE_IDEFAULTANSICODEPAGE,
+ LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3,
+ LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
+ LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3,
+ LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6,
+ LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9,
+ LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12
+ };
+
+ static char *nl_langinfo_buf = NULL;
+ static int nl_langinfo_len = 0;
+
+ if (nl_langinfo_len <= 0)
+ nl_langinfo_buf = xmalloc (nl_langinfo_len = 1);
+
+ if (item < 0 || item >= _NL_NUM)
+ nl_langinfo_buf[0] = 0;
+ else
+ {
+ LCID cloc = GetThreadLocale ();
+ int need_len = GetLocaleInfo (cloc, w32item[item] | LOCALE_USE_CP_ACP,
+ NULL, 0);
+
+ if (need_len <= 0)
+ nl_langinfo_buf[0] = 0;
+ else
+ {
+ if (item == CODESET)
+ {
+ need_len += 2; /* for the "cp" prefix */
+ if (need_len < 8) /* for the case we call GetACP */
+ need_len = 8;
+ }
+ if (nl_langinfo_len <= need_len)
+ nl_langinfo_buf = xrealloc (nl_langinfo_buf,
+ nl_langinfo_len = need_len);
+ if (!GetLocaleInfo (cloc, w32item[item] | LOCALE_USE_CP_ACP,
+ nl_langinfo_buf, nl_langinfo_len))
+ nl_langinfo_buf[0] = 0;
+ else if (item == CODESET)
+ {
+ if (strcmp (nl_langinfo_buf, "0") == 0 /* CP_ACP */
+ || strcmp (nl_langinfo_buf, "1") == 0) /* CP_OEMCP */
+ sprintf (nl_langinfo_buf, "cp%u", GetACP ());
+ else
+ {
+ memmove (nl_langinfo_buf + 2, nl_langinfo_buf,
+ strlen (nl_langinfo_buf) + 1);
+ nl_langinfo_buf[0] = 'c';
+ nl_langinfo_buf[1] = 'p';
+ }
+ }
+ }
+ }
+ return nl_langinfo_buf;
+}
+#endif /* HAVE_LANGINFO_CODESET */
DEFUN ("w32-get-locale-info", Fw32_get_locale_info,
Sw32_get_locale_info, 1, 2, 0,
{
Qhigh = intern ("high");
Qlow = intern ("low");
+ staticpro (&Qhigh);
+ staticpro (&Qlow);
#ifdef HAVE_SOCKETS
defsubr (&Sw32_has_winsock);
them blocking when trying to access unmounted drives etc. */);
Vw32_start_process_inherit_error_mode = Qt;
- DEFVAR_INT ("w32-pipe-read-delay", &Vw32_pipe_read_delay,
+ DEFVAR_INT ("w32-pipe-read-delay", &w32_pipe_read_delay,
doc: /* Forced delay before reading subprocess output.
This is done to improve the buffering of subprocess output, by
avoiding the inefficiency of frequently reading small amounts of data.
reading the subprocess output. If negative, the magnitude is the number
of time slices to wait (effectively boosting the priority of the child
process temporarily). A value of zero disables waiting entirely. */);
- Vw32_pipe_read_delay = 50;
+ w32_pipe_read_delay = 50;
DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names,
doc: /* Non-nil means convert all-upper case file names to lower case.
Note that this option is only useful for files on NTFS volumes, where hard links
are supported. Moreover, it slows down `file-attributes' noticeably. */);
Vw32_get_true_file_attributes = Qt;
+
+ staticpro (&Vw32_valid_locale_ids);
+ staticpro (&Vw32_valid_codepages);
}
/* end of ntproc.c */
+
+/* arch-tag: 23d3a34c-06d2-48a1-833b-ac7609aa5250
+ (do not change this comment) */