X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fntproc.c;h=561884767a8f31eb5862ac093461e120007227c8;hb=c38e15d3bb9aca515e15812f89145564556d3eb9;hp=aee5649904343c941d145d001c33f4fc5c2990bf;hpb=77dcef404dc78635f6ffa8f71a803d2bc7cc8921;p=chise%2Fxemacs-chise.git.1 diff --git a/src/ntproc.c b/src/ntproc.c index aee5649..5618847 100644 --- a/src/ntproc.c +++ b/src/ntproc.c @@ -42,14 +42,18 @@ Boston, MA 02111-1307, USA. #include #include - +#ifdef HAVE_A_OUT_H +#include +#endif #include "lisp.h" #include "sysproc.h" #include "nt.h" #include "ntheap.h" /* From 19.34.6 */ #include "systime.h" #include "syssignal.h" +#include "sysfile.h" #include "syswait.h" +#include "buffer.h" #include "process.h" /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */ @@ -86,6 +90,8 @@ Lisp_Object Vwin32_generate_fake_inodes; Lisp_Object Qhigh, Qlow; +extern Lisp_Object Vlisp_EXEC_SUFFIXES; + #ifndef DEBUG_XEMACS __inline #endif @@ -223,6 +229,63 @@ find_child_pid (DWORD pid) return NULL; } +/* Function to do blocking read of one byte, needed to implement + select. It is only allowed on sockets and pipes. */ +static int +_sys_read_ahead (int fd) +{ + child_process * cp; + int rc = 0; + + if (fd < 0 || fd >= MAXDESC) + return STATUS_READ_ERROR; + + cp = fd_info[fd].cp; + + if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY) + return STATUS_READ_ERROR; + + if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0 + || (fd_info[fd].flags & FILE_READ) == 0) + { + /* fd is not a pipe or socket */ + abort (); + } + + cp->status = STATUS_READ_IN_PROGRESS; + + if (fd_info[fd].flags & FILE_PIPE) + { + rc = _read (fd, &cp->chr, sizeof (char)); + + /* Give subprocess time to buffer some more output for us before + reporting that input is available; we need this because Win95 + connects DOS programs to pipes by making the pipe appear to be + the normal console stdout - as a result most DOS programs will + write to stdout without buffering, ie. one character at a + time. Even some Win32 programs do this - "dir" in a command + shell on NT is very slow if we don't do this. */ + if (rc > 0) + { + int wait = XINT (Vwin32_pipe_read_delay); + + if (wait > 0) + Sleep (wait); + else if (wait < 0) + while (++wait <= 0) + /* Yield remainder of our time slice, effectively giving a + temporary priority boost to the child process. */ + Sleep (0); + } + } + + if (rc == sizeof (char)) + cp->status = STATUS_READ_SUCCEEDED; + else + cp->status = STATUS_READ_FAILED; + + return cp->status; +} /* Thread proc for child process and socket reader threads. Each thread is normally blocked until woken by select() to check for input by @@ -330,7 +393,7 @@ reader_thread (void *arg) static const char * process_dir; static BOOL -create_child (char *exe, char *cmdline, char *env, +create_child (CONST char *exe, char *cmdline, char *env, int * pPid, child_process *cp) { STARTUPINFO start; @@ -402,8 +465,30 @@ create_child (char *exe, char *cmdline, char *env, 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 (char * filename, int * is_dos_app, int * is_cygnus_app) +win32_executable_type (CONST char * filename, int * is_dos_app, int * is_cygnus_app) { file_data executable; char * p; @@ -430,9 +515,9 @@ win32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app) /* Actually, I think it uses the program association for that extension, which is defined in the registry. */ p = egetenv ("COMSPEC"); - if (p) + 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 @@ -440,57 +525,77 @@ win32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app) start with a DOS program stub. Note that 16-bit Windows executables use the OS/2 1.x format. */ - IMAGE_DOS_HEADER * dos_header; - IMAGE_NT_HEADERS * nt_header; +#ifdef __MINGW32__ + /* mingw32 doesn't have enough headers to detect cygwin + apps, just do what we can. */ + FILHDR * exe_header; - dos_header = (PIMAGE_DOS_HEADER) executable.file_base; - if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) - goto unwind; + exe_header = (FILHDR*) executable.file_base; + if (exe_header->e_magic != DOSMAGIC) + 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++) + if ((char *) exe_header->e_lfanew > (char *) executable.size) { - char * dllname = RVA_TO_PTR (imports->Name, section, executable); - - if (strcmp (dllname, "cygwin.dll") == 0) + /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ + *is_dos_app = TRUE; + } + else if (exe_header->nt_signature != NT_SIGNATURE) { - *is_cygnus_app = TRUE; - break; + *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); + unwind: + close_file_data (&executable); } int -compare_env (const char **strp1, const char **strp2) +compare_env (const void *strp1, const void *strp2) { - const char *str1 = *strp1, *str2 = *strp2; + const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2; while (*str1 && *str2 && *str1 != '=' && *str2 != '=') { @@ -544,7 +649,7 @@ sys_spawnve (int mode, CONST char *cmdname, child_process *cp; int is_dos_app, is_cygnus_app; int do_quoting = 0; - char escape_char; + char escape_char = 0; /* We pass our process ID to our children by setting up an environment variable in their environment. */ char ppid_env_var_buffer[64]; @@ -564,24 +669,26 @@ sys_spawnve (int mode, CONST char *cmdname, if (NILP (Ffile_executable_p (program))) { full = Qnil; - locate_file (Vexec_path, program, EXEC_SUFFIXES, &full, 1); + locate_file (Vexec_path, program, Vlisp_EXEC_SUFFIXES, &full, 1); if (NILP (full)) { UNGCPRO; errno = EINVAL; return -1; } - cmdname = XSTRING_DATA (full); - /* #### KLUDGE */ - *(char**)(argv[0]) = cmdname; + GET_C_STRING_FILENAME_DATA_ALLOCA (full, cmdname); + } + else + { + (char*)cmdname = alloca (strlen (argv[0]) + 1); + strcpy ((char*)cmdname, argv[0]); } UNGCPRO; /* make sure argv[0] and cmdname are both in DOS format */ - strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); - unixtodos_filename (cmdname); + unixtodos_filename ((char*)cmdname); /* #### KLUDGE */ - *(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 @@ -597,13 +704,13 @@ sys_spawnve (int mode, CONST char *cmdname, { cmdname = alloca (MAXPATHLEN); if (egetenv ("CMDPROXY")) - strcpy (cmdname, egetenv ("CMDPROXY")); + strcpy ((char*)cmdname, egetenv ("CMDPROXY")); else { - strcpy (cmdname, XSTRING_DATA (Vinvocation_directory)); - strcat (cmdname, "cmdproxy.exe"); + strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory)); + strcat ((char*)cmdname, "cmdproxy.exe"); } - unixtodos_filename (cmdname); + unixtodos_filename ((char*)cmdname); } /* we have to do some conjuring here to put argv and envp into the @@ -649,7 +756,7 @@ sys_spawnve (int mode, CONST char *cmdname, /* do argv... */ arglen = 0; - targ = argv; + targ = (char**)argv; while (*targ) { char * p = *targ; @@ -695,7 +802,7 @@ sys_spawnve (int mode, CONST char *cmdname, arglen += strlen (*targ++) + 1; } cmdline = alloca (arglen); - targ = argv; + targ = (char**)argv; parg = cmdline; while (*targ) { @@ -776,7 +883,7 @@ sys_spawnve (int mode, CONST char *cmdname, /* and envp... */ arglen = 1; - targ = envp; + targ = (char**)envp; numenv = 1; /* for end null */ while (*targ) { @@ -791,7 +898,7 @@ sys_spawnve (int mode, CONST char *cmdname, /* merge env passed in and extra env into one, and sort it. */ targ = (char **) alloca (numenv * sizeof (char *)); - merge_and_sort_env (envp, extra_env, targ); + merge_and_sort_env ((char**)envp, extra_env, targ); /* concatenate env entries. */ env = alloca (arglen); @@ -882,7 +989,7 @@ sys_kill (int pid, int sig) pid = cp->procinfo.dwProcessId; /* Try to locate console window for process. */ - EnumWindows (find_child_console, (LPARAM) cp); + EnumWindows ((WNDENUMPROC)find_child_console, (LPARAM) cp); } if (sig == SIGINT) @@ -1335,9 +1442,6 @@ If successful, the new locale id is returned, otherwise nil. 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); @@ -1346,6 +1450,14 @@ syms_of_ntproc () DEFSUBR (Fwin32_get_default_locale_id); DEFSUBR (Fwin32_get_valid_locale_ids); DEFSUBR (Fwin32_set_current_locale); +} + + +void +vars_of_ntproc (void) +{ + Qhigh = intern ("high"); + Qlow = intern ("low"); DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* Non-nil enables quoting of process arguments to ensure correct parsing. @@ -1376,7 +1488,7 @@ or indirectly by Emacs), and preventing Emacs from cleanly terminating the subprocess group, but may allow Emacs to interrupt a subprocess that doesn't otherwise respond to interrupts from Emacs. */ ); - Vwin32_start_process_share_console = Qnil; + Vwin32_start_process_share_console = Qt; DEFVAR_LISP ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* Forced delay before reading subprocess output. @@ -1401,4 +1513,5 @@ the truename of a file can be slow. Vwin32_generate_fake_inodes = Qnil; #endif } + /* end of ntproc.c */