/* 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
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
*/
#include <fcntl.h>
#include <signal.h>
#include <sys/file.h>
+#include <setjmp.h>
/* must include CRT headers *before* config.h */
#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
#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 \
/* 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;
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;
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)
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;
{
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;
/* 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)
return TRUE;
EH_Fail:
- DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
+ DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError ()););
return FALSE;
}
}
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))
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
{
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. */
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.
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 '";
#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. */
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. */
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;
}
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
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. */
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,
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
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;
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);
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,
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 ();
#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[] = {
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)'.
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))
{
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)
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);
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);
}
\f
+void
syms_of_ntproc ()
{
DEFSYM (Qhigh, "high");
#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);