X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4dacf5c59890f619e2285e6afae1061c763d87fa..c3702194809d8772afa226d5107ec3abb05e8d35:/src/w32proc.c diff --git a/src/w32proc.c b/src/w32proc.c index ab76852765..ed405cce9f 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -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 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 @@ -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 . */ +/* Drew Bliss Oct 14, 1993 Adapted from alarm.c by Tim Fleehart */ @@ -63,6 +62,7 @@ extern BOOL WINAPI IsValidLocale(LCID, DWORD); #include "process.h" #include "syssignal.h" #include "w32term.h" +#include "dispextern.h" /* for xstrcasecmp */ #define RVA_TO_PTR(var,section,filedata) \ ((void *)((section)->PointerToRawData \ @@ -71,7 +71,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 +110,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; @@ -217,12 +218,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; @@ -267,7 +274,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) @@ -591,6 +598,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) { @@ -608,10 +622,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 @@ -651,33 +665,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; + } + } + } } } @@ -748,7 +783,14 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) 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) @@ -931,7 +973,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. */ @@ -1046,7 +1088,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. */ @@ -1143,7 +1185,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; @@ -1154,9 +1196,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 @@ -1222,7 +1264,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, @@ -1259,7 +1301,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 @@ -1757,9 +1799,14 @@ All path elements in FILENAME are converted to their long names. */) 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); @@ -1768,6 +1815,12 @@ All path elements in FILENAME are converted to their long names. */) 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); } @@ -2311,10 +2364,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 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);