Mercurial > hg > xemacs-beta
diff src/ntproc.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | da8ed4261e83 |
line wrap: on
line diff
--- a/src/ntproc.c Mon Aug 13 11:19:22 2007 +0200 +++ b/src/ntproc.c Mon Aug 13 11:20:41 2007 +0200 @@ -24,6 +24,15 @@ /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <io.h> +#include <fcntl.h> +#include <signal.h> + +/* must include CRT headers *before* config.h */ +/* ### I don't believe it - martin */ #include <config.h> #undef signal #undef wait @@ -32,6 +41,7 @@ #undef kill #include <windows.h> +#include <sys/socket.h> #ifdef HAVE_A_OUT_H #include <a.out.h> #endif @@ -45,9 +55,6 @@ #include "syswait.h" #include "buffer.h" #include "process.h" - -#include "console-msw.h" - /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */ /* #### I'm not going to play with shit. */ @@ -101,7 +108,7 @@ #endif } -/* sys_signal moved to nt.c. It's now called mswindows_signal... */ +/* sys_signal moved to nt.c. It's now called msw_signal... */ /* Defined in <process.h> which conflicts with the local copy */ #define _P_NOWAIT 1 @@ -386,7 +393,7 @@ static const char * process_dir; static BOOL -create_child (const char *exe, char *cmdline, char *env, +create_child (CONST char *exe, char *cmdline, char *env, int * pPid, child_process *cp) { STARTUPINFO start; @@ -399,6 +406,7 @@ xzero (start); start.cb = sizeof (start); +#ifdef HAVE_NTGUI if (NILP (Vwin32_start_process_show_window)) start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; else @@ -408,6 +416,7 @@ start.hStdInput = GetStdHandle (STD_INPUT_HANDLE); start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); start.hStdError = GetStdHandle (STD_ERROR_HANDLE); +#endif /* HAVE_NTGUI */ /* Explicitly specify no security */ if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION)) @@ -436,8 +445,16 @@ cp->procinfo.hThread=NULL; cp->procinfo.hProcess=NULL; + /* Hack for Windows 95, which assigns large (ie negative) pids */ + if (cp->pid < 0) + cp->pid = -cp->pid; + /* pid must fit in a Lisp_Int */ - +#ifdef USE_UNION_TYPE + cp->pid = (cp->pid & ((1U << VALBITS) - 1)); +#else + cp->pid = (cp->pid & VALMASK); +#endif *pPid = cp->pid; @@ -448,6 +465,155 @@ return FALSE; } +#ifndef __MINGW32__ +/* Return pointer to section header for section containing the given + relative virtual address. */ +static IMAGE_SECTION_HEADER * +rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header) +{ + PIMAGE_SECTION_HEADER section; + int i; + + section = IMAGE_FIRST_SECTION (nt_header); + + for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) + { + if (rva >= section->VirtualAddress + && rva < section->VirtualAddress + section->SizeOfRawData) + return section; + section++; + } + return NULL; +} +#endif + +void +win32_executable_type (CONST char * filename, int * is_dos_app, int * is_cygnus_app) +{ + file_data executable; + char * p; + + /* Default values in case we can't tell for sure. */ + *is_dos_app = FALSE; + *is_cygnus_app = FALSE; + + if (!open_input_file (&executable, filename)) + return; + + p = strrchr (filename, '.'); + + /* We can only identify DOS .com programs from the extension. */ + if (p && stricmp (p, ".com") == 0) + *is_dos_app = TRUE; + else if (p && (stricmp (p, ".bat") == 0 || + stricmp (p, ".cmd") == 0)) + { + /* A DOS shell script - it appears that CreateProcess is happy to + accept this (somewhat surprisingly); presumably it looks at + COMSPEC to determine what executable to actually invoke. + Therefore, we have to do the same here as well. */ + /* Actually, I think it uses the program association for that + extension, which is defined in the registry. */ + p = egetenv ("COMSPEC"); + if (p) + win32_executable_type (p, is_dos_app, is_cygnus_app); + } + else + { + /* Look for DOS .exe signature - if found, we must also check that + it isn't really a 16- or 32-bit Windows exe, since both formats + start with a DOS program stub. Note that 16-bit Windows + executables use the OS/2 1.x format. */ + +#ifdef __MINGW32__ + /* mingw32 doesn't have enough headers to detect cygwin + apps, just do what we can. */ + FILHDR * exe_header; + + exe_header = (FILHDR*) executable.file_base; + if (exe_header->e_magic != DOSMAGIC) + goto unwind; + + if ((char *) exe_header->e_lfanew > (char *) executable.size) + { + /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ + *is_dos_app = TRUE; + } + else if (exe_header->nt_signature != NT_SIGNATURE) + { + *is_dos_app = TRUE; + } +#else + IMAGE_DOS_HEADER * dos_header; + IMAGE_NT_HEADERS * nt_header; + + dos_header = (PIMAGE_DOS_HEADER) executable.file_base; + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) + goto unwind; + + nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew); + + if ((char *) nt_header > (char *) dos_header + executable.size) + { + /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ + *is_dos_app = TRUE; + } + else if (nt_header->Signature != IMAGE_NT_SIGNATURE && + LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) + { + *is_dos_app = TRUE; + } + 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); + + if (strcmp (dllname, "cygwin.dll") == 0) + { + *is_cygnus_app = TRUE; + break; + } + } + } +#endif + } + + unwind: + close_file_data (&executable); +} + +int +compare_env (const void *strp1, const void *strp2) +{ + const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2; + + while (*str1 && *str2 && *str1 != '=' && *str2 != '=') + { + if ((*str1) > (*str2)) + return 1; + else if ((*str1) < (*str2)) + return -1; + str1++, str2++; + } + + if (*str1 == '=' && *str2 == '=') + return 0; + else if (*str1 == '=') + return -1; + else + return 1; +} + void merge_and_sort_env (char **envp1, char **envp2, char **new_envp) { @@ -465,7 +631,7 @@ *nptr++ = *optr++; num += optr - envp2; - qsort (new_envp, num, sizeof (char*), compare_env); + qsort (new_envp, num, sizeof (char *), compare_env); *nptr = NULL; } @@ -473,8 +639,8 @@ /* When a new child process is created we need to register it in our list, so intercept spawn requests. */ int -sys_spawnve (int mode, const char *cmdname, - const char * const *argv, const char *const *envp) +sys_spawnve (int mode, CONST char *cmdname, + CONST char * CONST *argv, CONST char *CONST *envp) { Lisp_Object program, full; char *cmdline, *env, *parg, **targ; @@ -510,13 +676,11 @@ errno = EINVAL; return -1; } - TO_EXTERNAL_FORMAT (LISP_STRING, full, - C_STRING_ALLOCA, cmdname, - Qfile_name); + GET_C_STRING_FILENAME_DATA_ALLOCA (full, cmdname); } else { - cmdname = (char*)alloca (strlen (argv[0]) + 1); + (char*)cmdname = alloca (strlen (argv[0]) + 1); strcpy ((char*)cmdname, argv[0]); } UNGCPRO; @@ -524,21 +688,21 @@ /* make sure argv[0] and cmdname are both in DOS format */ unixtodos_filename ((char*)cmdname); /* #### KLUDGE */ - ((const char**)argv)[0] = cmdname; + ((CONST char**)argv)[0] = cmdname; /* Determine whether program is a 16-bit DOS executable, or a Win32 executable that is implicitly linked to the Cygnus dll (implying it was compiled with the Cygnus GNU toolchain and hence relies on cygwin.dll to parse the command line - we use this to decide how to escape quote chars in command line args that must be quoted). */ - mswindows_executable_type (cmdname, &is_dos_app, &is_cygnus_app); + win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app); /* On Windows 95, if cmdname is a DOS app, we invoke a helper application to start it by specifying the helper app as cmdname, while leaving the real app name as argv[0]. */ if (is_dos_app) { - cmdname = (char*) alloca (MAXPATHLEN); + cmdname = alloca (MAXPATHLEN); if (egetenv ("CMDPROXY")) strcpy ((char*)cmdname, egetenv ("CMDPROXY")); else @@ -585,7 +749,7 @@ /* Override escape char by binding win32-quote-process-args to desired character, or use t for auto-selection. */ if (INTP (Vwin32_quote_process_args)) - escape_char = (char) XINT (Vwin32_quote_process_args); + escape_char = XINT (Vwin32_quote_process_args); else escape_char = is_cygnus_app ? '"' : '\\'; } @@ -637,7 +801,7 @@ } arglen += strlen (*targ++) + 1; } - cmdline = (char*) alloca (arglen); + cmdline = alloca (arglen); targ = (char**)argv; parg = cmdline; while (*targ) @@ -719,7 +883,7 @@ /* and envp... */ arglen = 1; - targ = (char**) envp; + targ = (char**)envp; numenv = 1; /* for end null */ while (*targ) { @@ -733,11 +897,11 @@ numenv++; /* merge env passed in and extra env into one, and sort it. */ - targ = (char **) alloca (numenv * sizeof (char*)); - merge_and_sort_env ((char**) envp, extra_env, targ); + targ = (char **) alloca (numenv * sizeof (char *)); + merge_and_sort_env ((char**)envp, extra_env, targ); /* concatenate env entries. */ - env = (char*) alloca (arglen); + env = alloca (arglen); parg = env; while (*targ) { @@ -781,7 +945,7 @@ GetClassName (hwnd, window_class, sizeof (window_class)); if (strcmp (window_class, - mswindows_windows9x_p() + (os_subtype == OS_WIN95) ? "tty" : "ConsoleWindowClass") == 0) { @@ -874,7 +1038,7 @@ if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) { #if 1 - if (mswindows_windows9x_p()) + if (os_subtype == OS_WIN95) { /* Another possibility is to try terminating the VDM out-right by @@ -935,7 +1099,7 @@ #if 0 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */ -extern int report_file_error (const char *, Lisp_Object); +extern int report_file_error (CONST char *, Lisp_Object); #endif /* The following two routines are used to manipulate stdin, stdout, and stderr of our child processes. @@ -1028,6 +1192,12 @@ /* Some miscellaneous functions that are Windows specific, but not GUI specific (ie. are applicable in terminal or batch mode as well). */ +/* lifted from fileio.c */ +#define CORRECT_DIR_SEPS(s) \ + do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \ + else unixtodos_filename (s); \ + } while (0) + DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /* Return the short file name version (8.3) of the full path of FILENAME. If FILENAME does not exist, return nil. @@ -1257,7 +1427,7 @@ /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in w32term.h and defined in w32fns.c, both of which are not in current - XEmacs. #### Check what we lose by ifdef'ing out these. --marcpa */ + XEmacs. ### Check what we lose by ifdef'ing out these. --marcpa */ #if 0 /* Need to set input thread locale if present. */ if (dwWinThreadId) @@ -1270,8 +1440,11 @@ void -syms_of_ntproc (void) +syms_of_ntproc () { + Qhigh = intern ("high"); + Qlow = intern ("low"); + DEFSUBR (Fwin32_short_file_name); DEFSUBR (Fwin32_long_file_name); DEFSUBR (Fwin32_set_process_priority); @@ -1280,14 +1453,6 @@ DEFSUBR (Fwin32_get_default_locale_id); DEFSUBR (Fwin32_get_valid_locale_ids); DEFSUBR (Fwin32_set_current_locale); -} - - -void -vars_of_ntproc (void) -{ - defsymbol (&Qhigh, "high"); - defsymbol (&Qlow, "low"); DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* Non-nil enables quoting of process arguments to ensure correct parsing. @@ -1318,7 +1483,7 @@ subprocess group, but may allow Emacs to interrupt a subprocess that doesn't otherwise respond to interrupts from Emacs. */ ); - Vwin32_start_process_share_console = Qt; + Vwin32_start_process_share_console = Qnil; DEFVAR_LISP ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* Forced delay before reading subprocess output. @@ -1343,5 +1508,4 @@ Vwin32_generate_fake_inodes = Qnil; #endif } - /* end of ntproc.c */