/* Process support for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006, 2007, 2008 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 2, 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 "process.h"
#include "syssignal.h"
#include "w32term.h"
+#include "dispextern.h" /* for xstrcasecmp */
#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;
/* 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;
/* 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 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)
{
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
}
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;
+ }
+ }
+ }
}
}
variable in their environment. */
char ppid_env_var_buffer[64];
char *extra_env[] = {ppid_env_var_buffer, NULL};
- char *sepchars = " \t";
+ /* These are the characters that cause an argument to need quoting.
+ Arguments with whitespace characters need quoting to prevent the
+ argument being split into two or more. Arguments with wildcards
+ are also quoted, for consistency with posix platforms, where wildcards
+ are not expanded if we run the program directly without a shell.
+ Some extra whitespace characters need quoting in Cygwin programs,
+ so this list is conditionally modified below. */
+ char *sepchars = " \t*?";
/* We don't care about the other modes */
if (mode != _P_NOWAIT)
#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
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
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);
CORRECT_DIR_SEPS (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 build_string (longname);
}
#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 only
+useful for files on NTFS volumes, where hard links and file security are
+supported.
+
+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);