X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fntproc.c;h=eebf13ffdea02db8eff2d6be7600e802e3541e20;hb=4f29597e4f3696a59bb08ffece07183c1568c4a5;hp=aee5649904343c941d145d001c33f4fc5c2990bf;hpb=77dcef404dc78635f6ffa8f71a803d2bc7cc8921;p=chise%2Fxemacs-chise.git- diff --git a/src/ntproc.c b/src/ntproc.c index aee5649..eebf13f 100644 --- a/src/ntproc.c +++ b/src/ntproc.c @@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. #include /* must include CRT headers *before* config.h */ -/* ### I don't believe it - martin */ +/* #### I don't believe it - martin */ #include #undef signal #undef wait @@ -42,15 +42,22 @@ 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 "console-msw.h" + /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */ /* #### I'm not going to play with shit. */ @@ -86,6 +93,8 @@ Lisp_Object Vwin32_generate_fake_inodes; Lisp_Object Qhigh, Qlow; +extern Lisp_Object Vlisp_EXEC_SUFFIXES; + #ifndef DEBUG_XEMACS __inline #endif @@ -223,6 +232,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 +396,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; @@ -343,7 +409,6 @@ create_child (char *exe, char *cmdline, char *env, xzero (start); start.cb = sizeof (start); -#ifdef HAVE_NTGUI if (NILP (Vwin32_start_process_show_window)) start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; else @@ -353,7 +418,6 @@ create_child (char *exe, char *cmdline, char *env, 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)) @@ -382,16 +446,8 @@ create_child (char *exe, char *cmdline, char *env, 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; @@ -403,113 +459,6 @@ create_child (char *exe, char *cmdline, char *env, } void -win32_executable_type (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. */ - - 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; - } - } - } - } - -unwind: - close_file_data (&executable); -} - -int -compare_env (const char **strp1, const char **strp2) -{ - const char *str1 = *strp1, *str2 = *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) { char **optr, **nptr; @@ -526,7 +475,7 @@ merge_and_sort_env (char **envp1, char **envp2, char **new_envp) *nptr++ = *optr++; num += optr - envp2; - qsort (new_envp, num, sizeof (char *), compare_env); + qsort (new_envp, num, sizeof (char*), compare_env); *nptr = NULL; } @@ -534,8 +483,8 @@ merge_and_sort_env (char **envp1, char **envp2, char **new_envp) /* 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; @@ -544,7 +493,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,46 +513,50 @@ 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; + TO_EXTERNAL_FORMAT (LISP_STRING, full, + C_STRING_ALLOCA, cmdname, + Qfile_name); + } + else + { + cmdname = (char*)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 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). */ - win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app); + mswindows_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 = alloca (MAXPATHLEN); + cmdname = (char*) 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 @@ -642,14 +595,14 @@ sys_spawnve (int mode, CONST char *cmdname, /* 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 = XINT (Vwin32_quote_process_args); + escape_char = (char) XINT (Vwin32_quote_process_args); else escape_char = is_cygnus_app ? '"' : '\\'; } /* do argv... */ arglen = 0; - targ = argv; + targ = (char**)argv; while (*targ) { char * p = *targ; @@ -694,8 +647,8 @@ sys_spawnve (int mode, CONST char *cmdname, } arglen += strlen (*targ++) + 1; } - cmdline = alloca (arglen); - targ = argv; + cmdline = (char*) alloca (arglen); + targ = (char**)argv; parg = cmdline; while (*targ) { @@ -776,7 +729,7 @@ sys_spawnve (int mode, CONST char *cmdname, /* and envp... */ arglen = 1; - targ = envp; + targ = (char**) envp; numenv = 1; /* for end null */ while (*targ) { @@ -790,11 +743,11 @@ sys_spawnve (int mode, CONST char *cmdname, numenv++; /* 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); + targ = (char **) alloca (numenv * sizeof (char*)); + merge_and_sort_env ((char**) envp, extra_env, targ); /* concatenate env entries. */ - env = alloca (arglen); + env = (char*) alloca (arglen); parg = env; while (*targ) { @@ -838,7 +791,7 @@ find_child_console (HWND hwnd, child_process * cp) GetClassName (hwnd, window_class, sizeof (window_class)); if (strcmp (window_class, - (os_subtype == OS_WIN95) + msw_windows9x_p() ? "tty" : "ConsoleWindowClass") == 0) { @@ -882,7 +835,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) @@ -931,7 +884,7 @@ sys_kill (int pid, int sig) if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) { #if 1 - if (os_subtype == OS_WIN95) + if (msw_windows9x_p()) { /* Another possibility is to try terminating the VDM out-right by @@ -992,7 +945,7 @@ sys_kill (int pid, int sig) #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. @@ -1320,7 +1273,7 @@ If successful, the new locale id is returned, otherwise nil. /* 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) @@ -1333,11 +1286,8 @@ If successful, the new locale id is returned, otherwise nil. void -syms_of_ntproc () +syms_of_ntproc (void) { - Qhigh = intern ("high"); - Qlow = intern ("low"); - DEFSUBR (Fwin32_short_file_name); DEFSUBR (Fwin32_long_file_name); DEFSUBR (Fwin32_set_process_priority); @@ -1346,6 +1296,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) +{ + 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. @@ -1376,7 +1334,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 +1359,5 @@ the truename of a file can be slow. Vwin32_generate_fake_inodes = Qnil; #endif } + /* end of ntproc.c */