]> code.delx.au - gnu-emacs/blobdiff - src/w32proc.c
Add missing change from rel-22 branch to src/image.c
[gnu-emacs] / src / w32proc.c
index 7241784925c5b531b701970331064953c8100672..c21d589c525581b205ab53f9bf77932dd30197ce 100644 (file)
@@ -1,11 +1,12 @@
 /* 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,
@@ -15,8 +16,8 @@ GNU General Public License for more details.
 
 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
@@ -48,6 +49,11 @@ Boston, MA 02111-1307, USA.
 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"
@@ -57,6 +63,11 @@ extern BOOL WINAPI IsValidLocale(LCID, DWORD);
 #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
@@ -82,7 +93,7 @@ Lisp_Object Vw32_start_process_inherit_error_mode;
    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. */
@@ -205,12 +216,18 @@ delete_child (child_process *cp)
          /* 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;
@@ -274,7 +291,10 @@ reader_thread (void *arg)
     {
       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. */
@@ -367,7 +387,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
     cp->pid = -cp->pid;
 
   /* pid must fit in a Lisp_Int */
-  cp->pid = (cp->pid & VALMASK);
+  cp->pid = cp->pid & INTMASK;
 
   *pPid = cp->pid;
 
@@ -472,7 +492,8 @@ sys_wait (int *status)
     {
       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;
@@ -575,6 +596,13 @@ get_result:
   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)
 {
@@ -635,33 +663,54 @@ w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int
        }
       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;
+                    }
+                }
+            }
        }
     }
 
@@ -1218,7 +1267,7 @@ count_children:
     {
       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. */
@@ -1808,6 +1857,69 @@ If successful, the return value is t, otherwise nil.  */)
   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,
@@ -2141,6 +2253,8 @@ syms_of_ntproc ()
 {
   Qhigh = intern ("high");
   Qlow = intern ("low");
+  staticpro (&Qhigh);
+  staticpro (&Qlow);
 
 #ifdef HAVE_SOCKETS
   defsubr (&Sw32_has_winsock);
@@ -2202,7 +2316,7 @@ When non-nil, they inherit their error mode setting from Emacs, which stops
 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.
@@ -2211,7 +2325,7 @@ If positive, the value is the number of milliseconds to sleep before
 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.
@@ -2236,5 +2350,11 @@ the truename of a file can be slow.  */);
 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) */