]> code.delx.au - gnu-emacs/blobdiff - src/w32proc.c
Add 2012 to FSF copyright years for Emacs files (do not merge to trunk)
[gnu-emacs] / src / w32proc.c
index fbb4030e319c6184eef41c6f3158ad934a055fd2..4858db3ac4e730383ba0258f39126e9db412c8ef 100644 (file)
@@ -1,13 +1,13 @@
 /* Process support for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004,
-                2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+                2006, 2007, 2008, 2009, 2010, 2011, 2012  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,10 +15,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
+/*
    Drew Bliss                   Oct 14, 1993
      Adapted from alarm.c by Tim Fleehart
 */
@@ -30,6 +29,7 @@ Boston, MA 02110-1301, USA.
 #include <fcntl.h>
 #include <signal.h>
 #include <sys/file.h>
+#include <setjmp.h>
 
 /* must include CRT headers *before* config.h */
 
@@ -46,7 +46,7 @@ Boston, MA 02110-1301, USA.
 #include <windows.h>
 #ifdef __GNUC__
 /* This definition is missing from mingw32 headers. */
-extern BOOL WINAPI IsValidLocale(LCID, DWORD);
+extern BOOL WINAPI IsValidLocale (LCID, DWORD);
 #endif
 
 #ifdef HAVE_LANGINFO_CODESET
@@ -63,6 +63,8 @@ extern BOOL WINAPI IsValidLocale(LCID, DWORD);
 #include "process.h"
 #include "syssignal.h"
 #include "w32term.h"
+#include "dispextern.h"                /* for xstrcasecmp */
+#include "coding.h"
 
 #define RVA_TO_PTR(var,section,filedata) \
   ((void *)((section)->PointerToRawData                                        \
@@ -71,7 +73,7 @@ extern BOOL WINAPI IsValidLocale(LCID, DWORD);
 
 /* 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
+   are careful about constructing argv arrays, we make this behavior
    conditional (off by default). */
 Lisp_Object Vw32_quote_process_args;
 
@@ -110,6 +112,7 @@ Lisp_Object Vw32_generate_fake_inodes;
    exactly, at the expense of slower operation.  Since true hard links
    are supported on NTFS volumes, this is only relevant on NT.  */
 Lisp_Object Vw32_get_true_file_attributes;
+extern Lisp_Object Qlocal;
 
 Lisp_Object Qhigh, Qlow;
 
@@ -164,7 +167,7 @@ new_child (void)
   child_process *cp;
   DWORD id;
 
-  for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+  for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
     if (!CHILD_ACTIVE (cp))
       goto Initialise;
   if (child_proc_count == MAX_CHILDREN)
@@ -172,7 +175,7 @@ new_child (void)
   cp = &child_procs[child_proc_count++];
 
  Initialise:
-  memset (cp, 0, sizeof(*cp));
+  memset (cp, 0, sizeof (*cp));
   cp->fd = -1;
   cp->pid = -1;
   cp->procinfo.hProcess = NULL;
@@ -264,7 +267,7 @@ find_child_pid (DWORD pid)
 {
   child_process *cp;
 
-  for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+  for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
     if (CHILD_ACTIVE (cp) && pid == cp->pid)
       return cp;
   return NULL;
@@ -273,7 +276,7 @@ find_child_pid (DWORD pid)
 
 /* Thread proc for child process and socket reader threads. Each thread
    is normally blocked until woken by select() to check for input by
-   reading one char.  When the read completes, char_avail is signalled
+   reading one char.  When the read completes, char_avail is signaled
    to wake up the select emulator and the thread blocks itself again. */
 DWORD WINAPI
 reader_thread (void *arg)
@@ -395,7 +398,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
   return TRUE;
 
  EH_Fail:
-  DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
+  DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError ()););
   return FALSE;
 }
 
@@ -491,7 +494,7 @@ sys_wait (int *status)
     }
   else
     {
-      for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+      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
            && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
@@ -621,10 +624,10 @@ w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int
   p = strrchr (filename, '.');
 
   /* We can only identify DOS .com programs from the extension. */
-  if (p && stricmp (p, ".com") == 0)
+  if (p && xstrcasecmp (p, ".com") == 0)
     *is_dos_app = TRUE;
-  else if (p && (stricmp (p, ".bat") == 0
-                || stricmp (p, ".cmd") == 0))
+  else if (p && (xstrcasecmp (p, ".bat") == 0
+                || xstrcasecmp (p, ".cmd") == 0))
     {
       /* A DOS shell script - it appears that CreateProcess is happy to
         accept this (somewhat surprisingly); presumably it looks at
@@ -701,7 +704,7 @@ w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int
                 {
                   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.  */
@@ -869,7 +872,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
 
      Note that using backslash to escape embedded quotes requires
      additional special handling if an embedded quote is already
-     preceeded by backslash, or if an arg requiring quoting ends with
+     preceded by backslash, or if an arg requiring quoting ends with
      backslash.  In such cases, the run of escape characters needs to be
      doubled.  For consistency, we apply this special handling as long
      as the escape character is not quote.
@@ -888,7 +891,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
        escape_char = is_cygnus_app ? '"' : '\\';
     }
 
-  /* Cygwin apps needs quoting a bit more often */
+  /* Cygwin apps needs quoting a bit more often */
   if (escape_char == '"')
     sepchars = "\r\n\t\f '";
 
@@ -972,7 +975,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
 #if 0
          /* This version does not escape quotes if they occur at the
             beginning or end of the arg - this could lead to incorrect
-            behaviour when the arg itself represents a command line
+            behavior when the arg itself represents a command line
             containing quoted args.  I believe this was originally done
             as a hack to make some things work, before
             `w32-quote-process-args' was added.  */
@@ -1087,7 +1090,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
 
    To reduce the number of places in which Emacs can be hung such that
    C-g is not able to interrupt it, we always wait on interrupt_handle
-   (which is signalled by the input thread when C-g is detected).  If we
+   (which is signaled by the input thread when C-g is detected).  If we
    detect that we were woken up by C-g, we return -1 with errno set to
    EINTR as on Unix.  */
 
@@ -1184,7 +1187,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
                current_status = cp->status;
                if (WaitForSingleObject (cp->char_avail, 0) == WAIT_OBJECT_0)
                  {
-                   /* char_avail has been signalled, so status (which may
+                   /* char_avail has been signaled, so status (which may
                       have changed) should indicate read has completed
                       but has not been acknowledged. */
                    current_status = cp->status;
@@ -1195,9 +1198,9 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
                  }
                else
                  {
-                   /* char_avail has not been signalled, so status should
+                   /* char_avail has not been signaled, so status should
                       indicate that read is in progress; small possibility
-                      that read has completed but event wasn't yet signalled
+                      that read has completed but event wasn't yet signaled
                       when we tested it (because a context switch occurred
                       or if running on separate CPUs). */
                    if (current_status != STATUS_READ_READY
@@ -1238,7 +1241,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
 count_children:
   /* Add handles of child processes.  */
   nc = 0;
-  for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+  for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
     /* Some child_procs might be sockets; ignore them.  Also some
        children may have died already, but we haven't finished reading
        the process output; ignore them too.  */
@@ -1263,7 +1266,7 @@ count_children:
 
   start_time = GetTickCount ();
 
-  /* Wait for input or child death to be signalled.  If user input is
+  /* Wait for input or child death to be signaled.  If user input is
      allowed, then also accept window messages.  */
   if (FD_ISSET (0, &orfds))
     active = MsgWaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms,
@@ -1300,7 +1303,7 @@ count_children:
     abort ();
 
   /* Loop over all handles after active (now officially documented as
-     being the first signalled handle in the array).  We do this to
+     being the first signaled handle in the array).  We do this to
      ensure fairness, so that all channels with data available will be
      processed - otherwise higher numbered channels could be starved. */
   do
@@ -1716,7 +1719,7 @@ also loaded immediately if not already loaded.  If winsock is loaded,
 the winsock local hostname is returned (since this may be different from
 the value of `system-name' and should supplant it), otherwise t is
 returned to indicate winsock support is present.  */)
-  (load_now)
+     (load_now)
      Lisp_Object load_now;
 {
   int have_winsock;
@@ -1780,7 +1783,7 @@ All path elements in FILENAME are converted to their short names.  */)
   filename = Fexpand_file_name (filename, Qnil);
 
   /* luckily, this returns the short version of each element in the path.  */
-  if (GetShortPathName (SDATA (filename), shortname, MAX_PATH) == 0)
+  if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
     return Qnil;
 
   CORRECT_DIR_SEPS (shortname);
@@ -1794,22 +1797,33 @@ DEFUN ("w32-long-file-name", Fw32_long_file_name, Sw32_long_file_name,
        doc: /* Return the long file name version of the full path of FILENAME.
 If FILENAME does not exist, return nil.
 All path elements in FILENAME are converted to their long names.  */)
-  (filename)
+     (filename)
      Lisp_Object filename;
 {
   char longname[ MAX_PATH ];
+  int drive_only = 0;
 
   CHECK_STRING (filename);
 
+  if (SBYTES (filename) == 2
+      && *(SDATA (filename) + 1) == ':')
+    drive_only = 1;
+
   /* first expand it.  */
   filename = Fexpand_file_name (filename, Qnil);
 
-  if (!w32_get_long_filename (SDATA (filename), longname, MAX_PATH))
+  if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
     return Qnil;
 
   CORRECT_DIR_SEPS (longname);
 
-  return build_string (longname);
+  /* If we were passed only a drive, make sure that a slash is not appended
+     for consistency with directories.  Allow for drive mapping via SUBST
+     in case expand-file-name is ever changed to expand those.  */
+  if (drive_only && longname[1] == ':' && longname[2] == '/' && !longname[3])
+    longname[2] = '\0';
+
+  return DECODE_FILE (build_string (longname));
 }
 
 DEFUN ("w32-set-process-priority", Fw32_set_process_priority,
@@ -1821,7 +1835,7 @@ PRIORITY should be one of the symbols high, normal, or low;
 any other symbol will be interpreted as normal.
 
 If successful, the return value is t, otherwise nil.  */)
-  (process, priority)
+     (process, priority)
      Lisp_Object process, priority;
 {
   HANDLE proc_handle = GetCurrentProcess ();
@@ -1867,7 +1881,8 @@ If successful, the return value is t, otherwise nil.  */)
 
 #ifdef HAVE_LANGINFO_CODESET
 /* Emulation of nl_langinfo.  Used in fns.c:Flocale_info.  */
-char *nl_langinfo (nl_item item)
+char *
+nl_langinfo (nl_item item)
 {
   /* Conversion of Posix item numbers to their Windows equivalents.  */
   static const LCTYPE w32item[] = {
@@ -1933,7 +1948,7 @@ DEFUN ("w32-get-locale-info", Fw32_get_locale_info,
        Sw32_get_locale_info, 1, 2, 0,
        doc: /* Return information about the Windows locale LCID.
 By default, return a three letter locale code which encodes the default
-language as the first two characters, and the country or regionial variant
+language as the first two characters, and the country or regional variant
 as the third letter.  For example, ENU refers to `English (United States)',
 while ENC means `English (Canadian)'.
 
@@ -1970,7 +1985,7 @@ If LCID (a 16-bit number) is not a valid locale, the result is nil.  */)
                                LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
                                full_name, sizeof (full_name));
       if (got_full)
-       return build_string (full_name);
+       return DECODE_SYSTEM (build_string (full_name));
     }
   else if (NUMBERP (longform))
     {
@@ -1995,13 +2010,14 @@ human-readable form.  */)
   return make_number (GetThreadLocale ());
 }
 
-DWORD int_from_hex (char * s)
+DWORD
+int_from_hex (char * s)
 {
   DWORD val = 0;
   static char hex[] = "0123456789abcdefABCDEF";
   char * p;
 
-  while (*s && (p = strchr(hex, *s)) != NULL)
+  while (*s && (p = strchr (hex, *s)) != NULL)
     {
       unsigned digit = p - hex;
       if (digit > 15)
@@ -2016,7 +2032,8 @@ DWORD int_from_hex (char * s)
    function isn't given a context pointer.  */
 Lisp_Object Vw32_valid_locale_ids;
 
-BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
+BOOL CALLBACK
+enum_locale_fn (LPTSTR localeNum)
 {
   DWORD id = int_from_hex (localeNum);
   Vw32_valid_locale_ids = Fcons (make_number (id), Vw32_valid_locale_ids);
@@ -2081,7 +2098,8 @@ If successful, the new locale id is returned, otherwise nil.  */)
    function isn't given a context pointer.  */
 Lisp_Object Vw32_valid_codepages;
 
-BOOL CALLBACK enum_codepage_fn (LPTSTR codepageNum)
+BOOL CALLBACK
+enum_codepage_fn (LPTSTR codepageNum)
 {
   DWORD id = atoi (codepageNum);
   Vw32_valid_codepages = Fcons (make_number (id), Vw32_valid_codepages);
@@ -2257,6 +2275,7 @@ If successful, the new layout id is returned, otherwise nil.  */)
 }
 
 \f
+void
 syms_of_ntproc ()
 {
   DEFSYM (Qhigh, "high");
@@ -2352,10 +2371,19 @@ the truename of a file can be slow.  */);
 #endif
 
   DEFVAR_LISP ("w32-get-true-file-attributes", &Vw32_get_true_file_attributes,
-              doc: /* Non-nil means determine accurate link count in `file-attributes'.
-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;
+              doc: /* Non-nil means determine accurate file attributes in `file-attributes'.
+This option controls whether to issue additional system calls to determine
+accurate link counts, file type, and ownership information.  It is more
+useful for files on NTFS volumes, where hard links and file security are
+supported, than on volumes of the FAT family.
+
+Without these system calls, link count will always be reported as 1 and file
+ownership will be attributed to the current user.
+The default value `local' means only issue these system calls for files
+on local fixed drives.  A value of nil means never issue them.
+Any other non-nil value means do this even on remote and removable drives
+where the performance impact may be noticeable even on modern hardware.  */);
+  Vw32_get_true_file_attributes = Qlocal;
 
   staticpro (&Vw32_valid_locale_ids);
   staticpro (&Vw32_valid_codepages);