f144b04e294b3ade2502536a508ab705b0f744e8
[chise/xemacs-chise.git.1] / src / ntproc.c
1 /* Process support for Windows NT port of XEMACS.
2    Copyright (C) 1992, 1995 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20
21    Drew Bliss                   Oct 14, 1993
22      Adapted from alarm.c by Tim Fleehart */
23
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
25 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <io.h>
31 #include <fcntl.h>
32 #include <signal.h>
33
34 /* must include CRT headers *before* config.h */
35 /* ### I don't believe it - martin */
36 #include <config.h>
37 #undef signal
38 #undef wait
39 #undef spawnve
40 #undef select
41 #undef kill
42
43 #include <windows.h>
44 #include <sys/socket.h>
45
46 #include "lisp.h"
47 #include "sysproc.h"
48 #include "nt.h"
49 #include "ntheap.h" /* From 19.34.6 */
50 #include "systime.h"
51 #include "syssignal.h"
52 #include "syswait.h"
53 #include "process.h"
54 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */
55
56 /* #### I'm not going to play with shit. */
57 #pragma warning (disable:4013 4024 4090)
58
59 /* Control whether spawnve quotes arguments as necessary to ensure
60    correct parsing by child process.  Because not all uses of spawnve
61    are careful about constructing argv arrays, we make this behaviour
62    conditional (off by default). */
63 Lisp_Object Vwin32_quote_process_args;
64
65 /* Control whether create_child causes the process' window to be
66    hidden.  The default is nil. */
67 Lisp_Object Vwin32_start_process_show_window;
68
69 /* Control whether create_child causes the process to inherit Emacs'
70    console window, or be given a new one of its own.  The default is
71    nil, to allow multiple DOS programs to run on Win95.  Having separate
72    consoles also allows Emacs to cleanly terminate process groups.  */
73 Lisp_Object Vwin32_start_process_share_console;
74
75 /* Time to sleep before reading from a subprocess output pipe - this
76    avoids the inefficiency of frequently reading small amounts of data.
77    This is primarily necessary for handling DOS processes on Windows 95,
78    but is useful for Win32 processes on both Win95 and NT as well.  */
79 Lisp_Object Vwin32_pipe_read_delay;
80
81 /* Control whether stat() attempts to generate fake but hopefully
82    "accurate" inode values, by hashing the absolute truenames of files.
83    This should detect aliasing between long and short names, but still
84    allows the possibility of hash collisions.  */
85 Lisp_Object Vwin32_generate_fake_inodes;
86
87 Lisp_Object Qhigh, Qlow;
88
89 #ifndef DEBUG_XEMACS
90 __inline
91 #endif
92 void _DebPrint (const char *fmt, ...)
93 {
94 #ifdef DEBUG_XEMACS
95   char buf[1024];
96   va_list args;
97
98   va_start (args, fmt);
99   vsprintf (buf, fmt, args);
100   va_end (args);
101   OutputDebugString (buf);
102 #endif
103 }
104
105 /* sys_signal moved to nt.c. It's now called msw_signal... */
106
107 /* Defined in <process.h> which conflicts with the local copy */
108 #define _P_NOWAIT 1
109
110 /* Child process management list.  */
111 int child_proc_count = 0;
112 child_process child_procs[ MAX_CHILDREN ];
113 child_process *dead_child = NULL;
114
115 DWORD WINAPI reader_thread (void *arg);
116
117 /* Find an unused process slot.  */
118 child_process *
119 new_child (void)
120 {
121   child_process *cp;
122   DWORD id;
123   
124   for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
125     if (!CHILD_ACTIVE (cp))
126       goto Initialize;
127   if (child_proc_count == MAX_CHILDREN)
128     return NULL;
129   cp = &child_procs[child_proc_count++];
130
131  Initialize:
132   xzero (*cp);
133   cp->fd = -1;
134   cp->pid = -1;
135   cp->procinfo.hProcess = NULL;
136   cp->status = STATUS_READ_ERROR;
137
138   /* use manual reset event so that select() will function properly */
139   cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
140   if (cp->char_avail)
141     {
142       cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
143       if (cp->char_consumed)
144         {
145           cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
146           if (cp->thrd)
147             return cp;
148         }
149     }
150   delete_child (cp);
151   return NULL;
152 }
153
154 void 
155 delete_child (child_process *cp)
156 {
157   int i;
158
159   /* Should not be deleting a child that is still needed. */
160   for (i = 0; i < MAXDESC; i++)
161     if (fd_info[i].cp == cp)
162       abort ();
163
164   if (!CHILD_ACTIVE (cp))
165     return;
166
167   /* reap thread if necessary */
168   if (cp->thrd)
169     {
170       DWORD rc;
171
172       if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE)
173         {
174           /* let the thread exit cleanly if possible */
175           cp->status = STATUS_READ_ERROR;
176           SetEvent (cp->char_consumed);
177           if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0)
178             {
179               DebPrint (("delete_child.WaitForSingleObject (thread) failed "
180                          "with %lu for fd %ld\n", GetLastError (), cp->fd));
181               TerminateThread (cp->thrd, 0);
182             }
183         }
184       CloseHandle (cp->thrd);
185       cp->thrd = NULL;
186     }
187   if (cp->char_avail)
188     {
189       CloseHandle (cp->char_avail);
190       cp->char_avail = NULL;
191     }
192   if (cp->char_consumed)
193     {
194       CloseHandle (cp->char_consumed);
195       cp->char_consumed = NULL;
196     }
197
198   /* update child_proc_count (highest numbered slot in use plus one) */
199   if (cp == child_procs + child_proc_count - 1)
200     {
201       for (i = child_proc_count-1; i >= 0; i--)
202         if (CHILD_ACTIVE (&child_procs[i]))
203           {
204             child_proc_count = i + 1;
205             break;
206           }
207     }
208   if (i < 0)
209     child_proc_count = 0;
210 }
211
212 /* Find a child by pid.  */
213 static child_process *
214 find_child_pid (DWORD pid)
215 {
216   child_process *cp;
217
218   for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
219     if (CHILD_ACTIVE (cp) && pid == cp->pid)
220       return cp;
221   return NULL;
222 }
223
224
225 /* Thread proc for child process and socket reader threads. Each thread
226    is normally blocked until woken by select() to check for input by
227    reading one char.  When the read completes, char_avail is signalled
228    to wake up the select emulator and the thread blocks itself again. */
229 DWORD WINAPI 
230 reader_thread (void *arg)
231 {
232   child_process *cp;
233   
234   /* Our identity */
235   cp = (child_process *)arg;
236   
237   /* We have to wait for the go-ahead before we can start */
238   if (cp == NULL ||
239       WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
240     return 1;
241
242   for (;;)
243     {
244       int rc;
245
246       rc = _sys_read_ahead (cp->fd);
247
248       /* The name char_avail is a misnomer - it really just means the
249          read-ahead has completed, whether successfully or not. */
250       if (!SetEvent (cp->char_avail))
251         {
252           DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
253                      GetLastError (), cp->fd));
254           return 1;
255         }
256
257       if (rc == STATUS_READ_ERROR)
258         return 1;
259         
260       /* If the read died, the child has died so let the thread die */
261       if (rc == STATUS_READ_FAILED)
262         break;
263         
264       /* Wait until our input is acknowledged before reading again */
265       if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
266         {
267           DebPrint (("reader_thread.WaitForSingleObject failed with "
268                      "%lu for fd %ld\n", GetLastError (), cp->fd));
269           break;
270         }
271     }
272   return 0;
273 }
274
275 /* To avoid Emacs changing directory, we just record here the directory
276    the new process should start in.  This is set just before calling
277    sys_spawnve, and is not generally valid at any other time.  */
278 static const char * process_dir;
279
280 static BOOL 
281 create_child (char *exe, char *cmdline, char *env,
282               int * pPid, child_process *cp)
283 {
284   STARTUPINFO start;
285   SECURITY_ATTRIBUTES sec_attrs;
286   SECURITY_DESCRIPTOR sec_desc;
287   char dir[ MAXPATHLEN ];
288   
289   if (cp == NULL) abort ();
290   
291   xzero (start);
292   start.cb = sizeof (start);
293   
294 #ifdef HAVE_NTGUI
295   if (NILP (Vwin32_start_process_show_window))
296   start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
297   else
298     start.dwFlags = STARTF_USESTDHANDLES;
299   start.wShowWindow = SW_HIDE;
300
301   start.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
302   start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
303   start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
304 #endif /* HAVE_NTGUI */
305
306   /* Explicitly specify no security */
307   if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
308     goto EH_Fail;
309   if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
310     goto EH_Fail;
311   sec_attrs.nLength = sizeof (sec_attrs);
312   sec_attrs.lpSecurityDescriptor = &sec_desc;
313   sec_attrs.bInheritHandle = FALSE;
314   
315   strcpy (dir, process_dir);
316   unixtodos_filename (dir);
317   
318   if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
319                       (!NILP (Vwin32_start_process_share_console)
320                        ? CREATE_NEW_PROCESS_GROUP
321                        : CREATE_NEW_CONSOLE),
322                       env, dir,
323                       &start, &cp->procinfo))
324     goto EH_Fail;
325
326   cp->pid = (int) cp->procinfo.dwProcessId;
327
328   /* Hack for Windows 95, which assigns large (ie negative) pids */
329   if (cp->pid < 0)
330     cp->pid = -cp->pid;
331
332   /* pid must fit in a Lisp_Int */
333 #ifdef USE_UNION_TYPE
334   cp->pid = (cp->pid & ((1U << VALBITS) - 1));
335 #else
336   cp->pid = (cp->pid & VALMASK);
337 #endif
338
339   *pPid = cp->pid;
340   
341   return TRUE;
342   
343  EH_Fail:
344   DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
345   return FALSE;
346 }
347
348 void
349 win32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app)
350 {
351   file_data executable;
352   char * p;
353
354   /* Default values in case we can't tell for sure.  */
355   *is_dos_app = FALSE;
356   *is_cygnus_app = FALSE;
357
358   if (!open_input_file (&executable, filename))
359     return;
360
361   p = strrchr (filename, '.');
362
363       /* We can only identify DOS .com programs from the extension. */
364       if (p && stricmp (p, ".com") == 0)
365     *is_dos_app = TRUE;
366   else if (p && (stricmp (p, ".bat") == 0 ||
367                  stricmp (p, ".cmd") == 0))
368     {
369       /* A DOS shell script - it appears that CreateProcess is happy to
370          accept this (somewhat surprisingly); presumably it looks at
371          COMSPEC to determine what executable to actually invoke.
372              Therefore, we have to do the same here as well. */
373       /* Actually, I think it uses the program association for that
374          extension, which is defined in the registry.  */
375       p = egetenv ("COMSPEC");
376           if (p)
377         win32_executable_type (p, is_dos_app, is_cygnus_app);
378         }
379       else
380         {
381       /* Look for DOS .exe signature - if found, we must also check that
382          it isn't really a 16- or 32-bit Windows exe, since both formats
383          start with a DOS program stub.  Note that 16-bit Windows
384          executables use the OS/2 1.x format. */
385
386       IMAGE_DOS_HEADER * dos_header;
387       IMAGE_NT_HEADERS * nt_header;
388
389       dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
390       if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
391         goto unwind;
392
393       nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
394
395       if ((char *) nt_header > (char *) dos_header + executable.size) 
396         {
397           /* Some dos headers (pkunzip) have bogus e_lfanew fields.  */
398           *is_dos_app = TRUE;
399         } 
400       else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
401                  LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
402         {
403           *is_dos_app = TRUE;
404         }
405       else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
406         {
407           /* Look for cygwin.dll in DLL import list. */
408           IMAGE_DATA_DIRECTORY import_dir =
409             nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
410           IMAGE_IMPORT_DESCRIPTOR * imports;
411           IMAGE_SECTION_HEADER * section;
412
413           section = rva_to_section (import_dir.VirtualAddress, nt_header);
414           imports = RVA_TO_PTR (import_dir.VirtualAddress, section, executable);
415
416           for ( ; imports->Name; imports++)
417             {
418               char * dllname = RVA_TO_PTR (imports->Name, section, executable);
419
420               if (strcmp (dllname, "cygwin.dll") == 0)
421             {
422                   *is_cygnus_app = TRUE;
423                   break;
424                 }
425             }
426         }
427     }
428
429 unwind:
430   close_file_data (&executable);
431 }
432
433 int
434 compare_env (const char **strp1, const char **strp2)
435 {
436   const char *str1 = *strp1, *str2 = *strp2;
437
438   while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
439     {
440       if ((*str1) > (*str2))
441         return 1;
442       else if ((*str1) < (*str2))
443         return -1;
444       str1++, str2++;
445     }
446
447   if (*str1 == '=' && *str2 == '=')
448     return 0;
449   else if (*str1 == '=')
450     return -1;
451   else
452     return 1;
453 }
454
455 void
456 merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
457 {
458   char **optr, **nptr;
459   int num;
460
461   nptr = new_envp;
462   optr = envp1;
463   while (*optr)
464     *nptr++ = *optr++;
465   num = optr - envp1;
466
467   optr = envp2;
468   while (*optr)
469     *nptr++ = *optr++;
470   num += optr - envp2;
471
472   qsort (new_envp, num, sizeof (char *), compare_env);
473
474   *nptr = NULL;
475 }
476
477 /* When a new child process is created we need to register it in our list,
478    so intercept spawn requests.  */
479 int 
480 sys_spawnve (int mode, CONST char *cmdname,
481              CONST char * CONST *argv, CONST char *CONST *envp)
482 {
483   Lisp_Object program, full;
484   char *cmdline, *env, *parg, **targ;
485   int arglen, numenv;
486   int pid;
487   child_process *cp;
488   int is_dos_app, is_cygnus_app;
489   int do_quoting = 0;
490   char escape_char;
491   /* We pass our process ID to our children by setting up an environment
492      variable in their environment.  */
493   char ppid_env_var_buffer[64];
494   char *extra_env[] = {ppid_env_var_buffer, NULL};
495   struct gcpro gcpro1;
496     
497   /* We don't care about the other modes */
498   if (mode != _P_NOWAIT)
499     {
500       errno = EINVAL;
501       return -1;
502     }
503
504   /* Handle executable names without an executable suffix.  */
505   program = make_string (cmdname, strlen (cmdname));
506   GCPRO1 (program);
507   if (NILP (Ffile_executable_p (program)))
508     {
509       full = Qnil;
510       locate_file (Vexec_path, program, EXEC_SUFFIXES, &full, 1);
511       if (NILP (full))
512         {
513           UNGCPRO;
514           errno = EINVAL;
515           return -1;
516         }
517       cmdname = XSTRING_DATA (full);
518       /* #### KLUDGE */
519       *(char**)(argv[0]) = cmdname;
520     }
521   UNGCPRO;
522
523   /* make sure argv[0] and cmdname are both in DOS format */
524   strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]);
525   unixtodos_filename (cmdname);
526   /* #### KLUDGE */
527   *(char**)(argv[0]) = cmdname;
528
529   /* Determine whether program is a 16-bit DOS executable, or a Win32
530      executable that is implicitly linked to the Cygnus dll (implying it
531      was compiled with the Cygnus GNU toolchain and hence relies on
532      cygwin.dll to parse the command line - we use this to decide how to
533      escape quote chars in command line args that must be quoted). */
534   win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
535
536   /* On Windows 95, if cmdname is a DOS app, we invoke a helper
537      application to start it by specifying the helper app as cmdname,
538      while leaving the real app name as argv[0].  */
539   if (is_dos_app)
540     {
541       cmdname = alloca (MAXPATHLEN);
542       if (egetenv ("CMDPROXY"))
543         strcpy (cmdname, egetenv ("CMDPROXY"));
544       else
545     {
546           strcpy (cmdname, XSTRING_DATA (Vinvocation_directory));
547           strcat (cmdname, "cmdproxy.exe");
548         }
549       unixtodos_filename (cmdname);
550     }
551   
552   /* we have to do some conjuring here to put argv and envp into the
553      form CreateProcess wants...  argv needs to be a space separated/null
554      terminated list of parameters, and envp is a null
555      separated/double-null terminated list of parameters.
556
557      Additionally, zero-length args and args containing whitespace or
558      quote chars need to be wrapped in double quotes - for this to work,
559      embedded quotes need to be escaped as well.  The aim is to ensure
560      the child process reconstructs the argv array we start with
561      exactly, so we treat quotes at the beginning and end of arguments
562      as embedded quotes.
563
564      The Win32 GNU-based library from Cygnus doubles quotes to escape
565      them, while MSVC uses backslash for escaping.  (Actually the MSVC
566      startup code does attempt to recognise doubled quotes and accept
567      them, but gets it wrong and ends up requiring three quotes to get a
568      single embedded quote!)  So by default we decide whether to use
569      quote or backslash as the escape character based on whether the
570      binary is apparently a Cygnus compiled app.
571
572      Note that using backslash to escape embedded quotes requires
573      additional special handling if an embedded quote is already
574      preceeded by backslash, or if an arg requiring quoting ends with
575      backslash.  In such cases, the run of escape characters needs to be
576      doubled.  For consistency, we apply this special handling as long
577      as the escape character is not quote.
578    
579      Since we have no idea how large argv and envp are likely to be we
580      figure out list lengths on the fly and allocate them.  */
581   
582   if (!NILP (Vwin32_quote_process_args))
583     {
584       do_quoting = 1;
585       /* Override escape char by binding win32-quote-process-args to
586          desired character, or use t for auto-selection.  */
587       if (INTP (Vwin32_quote_process_args))
588         escape_char = XINT (Vwin32_quote_process_args);
589       else
590         escape_char = is_cygnus_app ? '"' : '\\';
591     }
592   
593   /* do argv...  */
594   arglen = 0;
595   targ = argv;
596   while (*targ)
597     {
598       char * p = *targ;
599       int need_quotes = 0;
600       int escape_char_run = 0;
601
602       if (*p == 0)
603         need_quotes = 1;
604       for ( ; *p; p++)
605         {
606           if (*p == '"')
607           {
608               /* allow for embedded quotes to be escaped */
609             arglen++;
610               need_quotes = 1;
611               /* handle the case where the embedded quote is already escaped */
612               if (escape_char_run > 0)
613                 {
614                   /* To preserve the arg exactly, we need to double the
615                      preceding escape characters (plus adding one to
616                      escape the quote character itself).  */
617                   arglen += escape_char_run;
618           }
619             }
620       else if (*p == ' ' || *p == '\t')
621             {
622               need_quotes = 1;
623             }
624
625           if (*p == escape_char && escape_char != '"')
626             escape_char_run++;
627           else
628             escape_char_run = 0;
629         }
630       if (need_quotes)
631         {
632         arglen += 2;
633           /* handle the case where the arg ends with an escape char - we
634              must not let the enclosing quote be escaped.  */
635           if (escape_char_run > 0)
636             arglen += escape_char_run;
637         }
638       arglen += strlen (*targ++) + 1;
639     }
640   cmdline = alloca (arglen);
641   targ = argv;
642   parg = cmdline;
643   while (*targ)
644     {
645       char * p = *targ;
646       int need_quotes = 0;
647
648       if (*p == 0)
649         need_quotes = 1;
650
651       if (do_quoting)
652         {
653           for ( ; *p; p++)
654             if (*p == ' ' || *p == '\t' || *p == '"')
655               need_quotes = 1;
656         }
657       if (need_quotes)
658         {
659           int escape_char_run = 0;
660           char * first;
661           char * last;
662
663           p = *targ;
664           first = p;
665           last = p + strlen (p) - 1;
666           *parg++ = '"';
667 #if 0
668           /* This version does not escape quotes if they occur at the
669              beginning or end of the arg - this could lead to incorrect
670              behaviour when the arg itself represents a command line
671              containing quoted args.  I believe this was originally done
672              as a hack to make some things work, before
673              `win32-quote-process-args' was added.  */
674           while (*p)
675             {
676               if (*p == '"' && p > first && p < last)
677                 *parg++ = escape_char;  /* escape embedded quotes */
678               *parg++ = *p++;
679             }
680 #else
681           for ( ; *p; p++)
682             {
683               if (*p == '"')
684                 {
685                   /* double preceding escape chars if any */
686                   while (escape_char_run > 0)
687                     {
688                       *parg++ = escape_char;
689                       escape_char_run--;
690                     }
691                   /* escape all quote chars, even at beginning or end */
692                   *parg++ = escape_char;
693                 }
694               *parg++ = *p;
695
696               if (*p == escape_char && escape_char != '"')
697                 escape_char_run++;
698               else
699                 escape_char_run = 0;
700             }
701           /* double escape chars before enclosing quote */
702           while (escape_char_run > 0)
703             {
704               *parg++ = escape_char;
705               escape_char_run--;
706             }
707 #endif
708           *parg++ = '"';
709         }
710       else
711         {
712           strcpy (parg, *targ);
713           parg += strlen (*targ);
714         }
715       *parg++ = ' ';
716       targ++;
717     }
718   *--parg = '\0';
719   
720   /* and envp...  */
721   arglen = 1;
722   targ = envp;
723   numenv = 1; /* for end null */
724   while (*targ)
725     {
726       arglen += strlen (*targ++) + 1;
727       numenv++;
728     }
729   /* extra env vars... */
730   sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d", 
731            GetCurrentProcessId ());
732   arglen += strlen (ppid_env_var_buffer) + 1;
733   numenv++;
734
735   /* merge env passed in and extra env into one, and sort it.  */
736   targ = (char **) alloca (numenv * sizeof (char *));
737   merge_and_sort_env (envp, extra_env, targ);
738
739   /* concatenate env entries.  */
740   env = alloca (arglen);
741   parg = env;
742   while (*targ)
743     {
744       strcpy (parg, *targ);
745       parg += strlen (*targ++);
746       *parg++ = '\0';
747     }
748   *parg++ = '\0';
749   *parg = '\0';
750
751   cp = new_child ();
752   if (cp == NULL)
753     {
754       errno = EAGAIN;
755       return -1;
756     }
757   
758   /* Now create the process.  */
759   if (!create_child (cmdname, cmdline, env, &pid, cp))
760     {
761       delete_child (cp);
762       errno = ENOEXEC;
763       return -1;
764     }
765
766   return pid;
767 }
768
769 /* Substitute for certain kill () operations */
770
771 static BOOL CALLBACK
772 find_child_console (HWND hwnd, child_process * cp)
773 {
774   DWORD thread_id;
775   DWORD process_id;
776
777   thread_id = GetWindowThreadProcessId (hwnd, &process_id);
778   if (process_id == cp->procinfo.dwProcessId)
779     {
780       char window_class[32];
781
782       GetClassName (hwnd, window_class, sizeof (window_class));
783       if (strcmp (window_class,
784                   (os_subtype == OS_WIN95)
785                   ? "tty"
786                   : "ConsoleWindowClass") == 0)
787         {
788           cp->hwnd = hwnd;
789           return FALSE;
790         }
791     }
792   /* keep looking */
793   return TRUE;
794 }
795
796 int 
797 sys_kill (int pid, int sig)
798 {
799   child_process *cp;
800   HANDLE proc_hand;
801   int need_to_free = 0;
802   int rc = 0;
803   
804   /* Only handle signals that will result in the process dying */
805   if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
806     {
807       errno = EINVAL;
808       return -1;
809     }
810
811   cp = find_child_pid (pid);
812   if (cp == NULL)
813     {
814       proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
815       if (proc_hand == NULL)
816         {
817           errno = EPERM;
818           return -1;
819         }
820       need_to_free = 1;
821     }
822   else
823     {
824       proc_hand = cp->procinfo.hProcess;
825       pid = cp->procinfo.dwProcessId;
826
827       /* Try to locate console window for process. */
828       EnumWindows (find_child_console, (LPARAM) cp);
829     }
830   
831   if (sig == SIGINT)
832     {
833       if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
834         {
835           BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
836           BYTE vk_break_code = VK_CANCEL;
837           BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
838           HWND foreground_window;
839
840           if (break_scan_code == 0)
841             {
842               /* Fake Ctrl-C if we can't manage Ctrl-Break. */
843               vk_break_code = 'C';
844               break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
845             }
846
847           foreground_window = GetForegroundWindow ();
848           if (foreground_window && SetForegroundWindow (cp->hwnd))
849             {
850               /* Generate keystrokes as if user had typed Ctrl-Break or Ctrl-C.  */
851               keybd_event (VK_CONTROL, control_scan_code, 0, 0);
852               keybd_event (vk_break_code, break_scan_code, 0, 0);
853               keybd_event (vk_break_code, break_scan_code, KEYEVENTF_KEYUP, 0);
854               keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
855
856               /* Sleep for a bit to give time for Emacs frame to respond
857                  to focus change events (if Emacs was active app).  */
858               Sleep (10);
859
860               SetForegroundWindow (foreground_window);
861             }
862         }
863       /* Ctrl-Break is NT equivalent of SIGINT.  */
864       else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
865         {
866           DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
867                      "for pid %lu\n", GetLastError (), pid));
868           errno = EINVAL;
869           rc = -1;
870         }
871     }
872   else
873     {
874       if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd)
875         {
876 #if 1
877           if (os_subtype == OS_WIN95)
878             {
879 /*
880    Another possibility is to try terminating the VDM out-right by
881    calling the Shell VxD (id 0x17) V86 interface, function #4
882    "SHELL_Destroy_VM", ie.
883
884      mov edx,4
885      mov ebx,vm_handle
886      call shellapi
887
888    First need to determine the current VM handle, and then arrange for
889    the shellapi call to be made from the system vm (by using
890    Switch_VM_and_callback).
891
892    Could try to invoke DestroyVM through CallVxD.
893
894 */
895 #if 0
896               /* On Win95, posting WM_QUIT causes the 16-bit subsystem
897                  to hang when cmdproxy is used in conjunction with
898                  command.com for an interactive shell.  Posting
899                  WM_CLOSE pops up a dialog that, when Yes is selected,
900                  does the same thing.  TerminateProcess is also less
901                  than ideal in that subprocesses tend to stick around
902                  until the machine is shutdown, but at least it
903                  doesn't freeze the 16-bit subsystem.  */
904               PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
905 #endif
906               if (!TerminateProcess (proc_hand, 0xff))
907                 {
908                   DebPrint (("sys_kill.TerminateProcess returned %d "
909                              "for pid %lu\n", GetLastError (), pid));
910                   errno = EINVAL;
911                   rc = -1;
912                 }
913             }
914           else
915 #endif
916             PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
917         }
918       /* Kill the process.  On Win32 this doesn't kill child processes
919          so it doesn't work very well for shells which is why it's not
920          used in every case.  */
921       else if (!TerminateProcess (proc_hand, 0xff))
922         {
923           DebPrint (("sys_kill.TerminateProcess returned %d "
924                      "for pid %lu\n", GetLastError (), pid));
925           errno = EINVAL;
926           rc = -1;
927         }
928     }
929
930   if (need_to_free)
931     CloseHandle (proc_hand);
932
933   return rc;
934 }
935
936 #if 0
937 /* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */
938 extern int report_file_error (CONST char *, Lisp_Object);
939 #endif
940 /* The following two routines are used to manipulate stdin, stdout, and
941    stderr of our child processes.
942
943    Assuming that in, out, and err are *not* inheritable, we make them
944    stdin, stdout, and stderr of the child as follows:
945
946    - Save the parent's current standard handles.
947    - Set the std handles to inheritable duplicates of the ones being passed in.
948      (Note that _get_osfhandle() is an io.h procedure that retrieves the
949      NT file handle for a crt file descriptor.)
950    - Spawn the child, which inherits in, out, and err as stdin,
951      stdout, and stderr. (see Spawnve)
952    - Close the std handles passed to the child.
953    - Reset the parent's standard handles to the saved handles.
954      (see reset_standard_handles)
955    We assume that the caller closes in, out, and err after calling us.  */
956
957 void
958 prepare_standard_handles (int in, int out, int err, HANDLE handles[3])
959 {
960   HANDLE parent;
961   HANDLE newstdin, newstdout, newstderr;
962
963   parent = GetCurrentProcess ();
964
965   handles[0] = GetStdHandle (STD_INPUT_HANDLE);
966   handles[1] = GetStdHandle (STD_OUTPUT_HANDLE);
967   handles[2] = GetStdHandle (STD_ERROR_HANDLE);
968
969   /* make inheritable copies of the new handles */
970   if (!DuplicateHandle (parent, 
971                        (HANDLE) _get_osfhandle (in),
972                        parent,
973                        &newstdin, 
974                        0, 
975                        TRUE, 
976                        DUPLICATE_SAME_ACCESS))
977     report_file_error ("Duplicating input handle for child", Qnil);
978   
979   if (!DuplicateHandle (parent,
980                        (HANDLE) _get_osfhandle (out),
981                        parent,
982                        &newstdout,
983                        0,
984                        TRUE,
985                        DUPLICATE_SAME_ACCESS))
986     report_file_error ("Duplicating output handle for child", Qnil);
987   
988   if (!DuplicateHandle (parent,
989                        (HANDLE) _get_osfhandle (err),
990                        parent,
991                        &newstderr,
992                        0,
993                        TRUE,
994                        DUPLICATE_SAME_ACCESS))
995     report_file_error ("Duplicating error handle for child", Qnil);
996
997   /* and store them as our std handles */
998   if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
999     report_file_error ("Changing stdin handle", Qnil);
1000   
1001   if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
1002     report_file_error ("Changing stdout handle", Qnil);
1003
1004   if (!SetStdHandle (STD_ERROR_HANDLE, newstderr))
1005     report_file_error ("Changing stderr handle", Qnil);
1006 }
1007
1008 void
1009 reset_standard_handles (int in, int out, int err, HANDLE handles[3])
1010 {
1011   /* close the duplicated handles passed to the child */
1012   CloseHandle (GetStdHandle (STD_INPUT_HANDLE));
1013   CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE));
1014   CloseHandle (GetStdHandle (STD_ERROR_HANDLE));
1015
1016   /* now restore parent's saved std handles */
1017   SetStdHandle (STD_INPUT_HANDLE, handles[0]);
1018   SetStdHandle (STD_OUTPUT_HANDLE, handles[1]);
1019   SetStdHandle (STD_ERROR_HANDLE, handles[2]);
1020 }
1021
1022 void
1023 set_process_dir (const char * dir)
1024 {
1025   process_dir = dir;
1026 }
1027 \f
1028 /* Some miscellaneous functions that are Windows specific, but not GUI
1029    specific (ie. are applicable in terminal or batch mode as well).  */
1030
1031 /* lifted from fileio.c  */
1032 #define CORRECT_DIR_SEPS(s) \
1033   do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
1034        else unixtodos_filename (s); \
1035   } while (0)
1036
1037 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /*
1038   Return the short file name version (8.3) of the full path of FILENAME.
1039 If FILENAME does not exist, return nil.
1040 All path elements in FILENAME are converted to their short names.
1041 */
1042        (filename))
1043 {
1044   char shortname[MAX_PATH];
1045
1046   CHECK_STRING (filename);
1047
1048   /* first expand it.  */
1049   filename = Fexpand_file_name (filename, Qnil);
1050
1051   /* luckily, this returns the short version of each element in the path.  */
1052   if (GetShortPathName (XSTRING_DATA (filename), shortname, MAX_PATH) == 0)
1053     return Qnil;
1054
1055   CORRECT_DIR_SEPS (shortname);
1056
1057   return build_string (shortname);
1058 }
1059
1060
1061 DEFUN ("win32-long-file-name", Fwin32_long_file_name, 1, 1, "", /*
1062   Return the long file name version of the full path of FILENAME.
1063 If FILENAME does not exist, return nil.
1064 All path elements in FILENAME are converted to their long names.
1065 */
1066        (filename))
1067 {
1068   char longname[ MAX_PATH ];
1069
1070   CHECK_STRING (filename);
1071
1072   /* first expand it.  */
1073   filename = Fexpand_file_name (filename, Qnil);
1074
1075   if (!win32_get_long_filename (XSTRING_DATA (filename), longname, MAX_PATH))
1076     return Qnil;
1077
1078   CORRECT_DIR_SEPS (longname);
1079
1080   return build_string (longname);
1081 }
1082
1083 DEFUN ("win32-set-process-priority", Fwin32_set_process_priority, 2, 2, "", /*
1084   Set the priority of PROCESS to PRIORITY.
1085 If PROCESS is nil, the priority of Emacs is changed, otherwise the
1086 priority of the process whose pid is PROCESS is changed.
1087 PRIORITY should be one of the symbols high, normal, or low;
1088 any other symbol will be interpreted as normal.
1089
1090 If successful, the return value is t, otherwise nil.
1091 */
1092        (process, priority))
1093 {
1094   HANDLE proc_handle = GetCurrentProcess ();
1095   DWORD  priority_class = NORMAL_PRIORITY_CLASS;
1096   Lisp_Object result = Qnil;
1097
1098   CHECK_SYMBOL (priority);
1099
1100   if (!NILP (process))
1101     {
1102       DWORD pid;
1103       child_process *cp;
1104
1105       CHECK_INT (process);
1106
1107       /* Allow pid to be an internally generated one, or one obtained
1108          externally.  This is necessary because real pids on Win95 are
1109          negative.  */
1110
1111       pid = XINT (process);
1112       cp = find_child_pid (pid);
1113       if (cp != NULL)
1114         pid = cp->procinfo.dwProcessId;
1115
1116       proc_handle = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid);
1117     }
1118
1119   if (EQ (priority, Qhigh))
1120     priority_class = HIGH_PRIORITY_CLASS;
1121   else if (EQ (priority, Qlow))
1122     priority_class = IDLE_PRIORITY_CLASS;
1123
1124   if (proc_handle != NULL)
1125     {
1126       if (SetPriorityClass (proc_handle, priority_class))
1127         result = Qt;
1128       if (!NILP (process))
1129         CloseHandle (proc_handle);
1130     }
1131
1132   return result;
1133 }
1134
1135
1136 DEFUN ("win32-get-locale-info", Fwin32_get_locale_info, 1, 2, "", /*
1137   "Return information about the Windows locale LCID.
1138 By default, return a three letter locale code which encodes the default
1139 language as the first two characters, and the country or regionial variant
1140 as the third letter.  For example, ENU refers to `English (United States)',
1141 while ENC means `English (Canadian)'.
1142
1143 If the optional argument LONGFORM is non-nil, the long form of the locale
1144 name is returned, e.g. `English (United States)' instead.
1145
1146 If LCID (a 16-bit number) is not a valid locale, the result is nil.
1147 */
1148      (lcid, longform))
1149 {
1150   int got_abbrev;
1151   int got_full;
1152   char abbrev_name[32] = { 0 };
1153   char full_name[256] = { 0 };
1154
1155   CHECK_INT (lcid);
1156
1157   if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1158     return Qnil;
1159
1160   if (NILP (longform))
1161     {
1162       got_abbrev = GetLocaleInfo (XINT (lcid),
1163                                   LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1164                                   abbrev_name, sizeof (abbrev_name));
1165       if (got_abbrev)
1166         return build_string (abbrev_name);
1167     }
1168   else
1169     {
1170       got_full = GetLocaleInfo (XINT (lcid),
1171                                 LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
1172                                 full_name, sizeof (full_name));
1173       if (got_full)
1174         return build_string (full_name);
1175     }
1176
1177   return Qnil;
1178 }
1179
1180
1181 DEFUN ("win32-get-current-locale-id", Fwin32_get_current_locale_id, 0, 0, "", /*
1182   "Return Windows locale id for current locale setting.
1183 This is a numerical value; use `win32-get-locale-info' to convert to a
1184 human-readable form.
1185 */
1186        ())
1187 {
1188   return make_int (GetThreadLocale ());
1189 }
1190
1191
1192 DEFUN ("win32-get-default-locale-id", Fwin32_get_default_locale_id, 0, 1, "", /*
1193   "Return Windows locale id for default locale setting.
1194 By default, the system default locale setting is returned; if the optional
1195 parameter USERP is non-nil, the user default locale setting is returned.
1196 This is a numerical value; use `win32-get-locale-info' to convert to a
1197 human-readable form.
1198 */
1199        (userp))
1200 {
1201   if (NILP (userp))
1202     return make_int (GetSystemDefaultLCID ());
1203   return make_int (GetUserDefaultLCID ());
1204 }
1205
1206 DWORD int_from_hex (char * s)
1207 {
1208   DWORD val = 0;
1209   static char hex[] = "0123456789abcdefABCDEF";
1210   char * p;
1211
1212   while (*s && (p = strchr(hex, *s)) != NULL)
1213     {
1214       unsigned digit = p - hex;
1215       if (digit > 15)
1216         digit -= 6;
1217       val = val * 16 + digit;
1218       s++;
1219     }
1220   return val;
1221 }
1222
1223 /* We need to build a global list, since the EnumSystemLocale callback
1224    function isn't given a context pointer.  */
1225 Lisp_Object Vwin32_valid_locale_ids;
1226
1227 BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
1228 {
1229   DWORD id = int_from_hex (localeNum);
1230   Vwin32_valid_locale_ids = Fcons (make_int (id), Vwin32_valid_locale_ids);
1231   return TRUE;
1232 }
1233
1234 DEFUN ("win32-get-valid-locale-ids", Fwin32_get_valid_locale_ids, 0, 0, "", /*
1235   Return list of all valid Windows locale ids.
1236 Each id is a numerical value; use `win32-get-locale-info' to convert to a
1237 human-readable form.
1238 */
1239        ())
1240 {
1241   Vwin32_valid_locale_ids = Qnil;
1242
1243   EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED);
1244
1245   Vwin32_valid_locale_ids = Fnreverse (Vwin32_valid_locale_ids);
1246   return Vwin32_valid_locale_ids;
1247 }
1248
1249
1250 DEFUN ("win32-set-current-locale", Fwin32_set_current_locale, 1, 1, "", /*
1251   Make Windows locale LCID be the current locale setting for Emacs.
1252 If successful, the new locale id is returned, otherwise nil.
1253 */
1254      (lcid))
1255 {
1256   CHECK_INT (lcid);
1257
1258   if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1259     return Qnil;
1260
1261   if (!SetThreadLocale (XINT (lcid)))
1262     return Qnil;
1263
1264 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in
1265    w32term.h and defined in w32fns.c, both of which are not in current
1266    XEmacs.  ### Check what we lose by ifdef'ing out these. --marcpa */
1267 #if 0
1268   /* Need to set input thread locale if present.  */
1269   if (dwWinThreadId)
1270     /* Reply is not needed.  */
1271     PostThreadMessage (dwWinThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0);
1272 #endif
1273
1274   return make_int (GetThreadLocale ());
1275 }
1276
1277 \f
1278 void
1279 syms_of_ntproc ()
1280 {
1281   Qhigh = intern ("high");
1282   Qlow = intern ("low");
1283
1284   DEFSUBR (Fwin32_short_file_name);
1285   DEFSUBR (Fwin32_long_file_name);
1286   DEFSUBR (Fwin32_set_process_priority);
1287   DEFSUBR (Fwin32_get_locale_info);
1288   DEFSUBR (Fwin32_get_current_locale_id);
1289   DEFSUBR (Fwin32_get_default_locale_id);
1290   DEFSUBR (Fwin32_get_valid_locale_ids);
1291   DEFSUBR (Fwin32_set_current_locale);
1292
1293   DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /*
1294     Non-nil enables quoting of process arguments to ensure correct parsing.
1295 Because Windows does not directly pass argv arrays to child processes,
1296 programs have to reconstruct the argv array by parsing the command
1297 line string.  For an argument to contain a space, it must be enclosed
1298 in double quotes or it will be parsed as multiple arguments.
1299
1300 If the value is a character, that character will be used to escape any
1301 quote characters that appear, otherwise a suitable escape character
1302 will be chosen based on the type of the program.
1303 */ );
1304   Vwin32_quote_process_args = Qt;
1305
1306   DEFVAR_LISP ("win32-start-process-show-window",
1307                &Vwin32_start_process_show_window /*
1308     When nil, processes started via start-process hide their windows.
1309 When non-nil, they show their window in the method of their choice.
1310 */ );
1311   Vwin32_start_process_show_window = Qnil;
1312
1313   DEFVAR_LISP ("win32-start-process-share-console",
1314                &Vwin32_start_process_share_console /*
1315     When nil, processes started via start-process are given a new console.
1316 When non-nil, they share the Emacs console; this has the limitation of
1317 allowing only only DOS subprocess to run at a time (whether started directly
1318 or indirectly by Emacs), and preventing Emacs from cleanly terminating the
1319 subprocess group, but may allow Emacs to interrupt a subprocess that doesn't
1320 otherwise respond to interrupts from Emacs.
1321 */ );
1322   Vwin32_start_process_share_console = Qnil;
1323
1324   DEFVAR_LISP ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /*
1325     Forced delay before reading subprocess output.
1326 This is done to improve the buffering of subprocess output, by
1327 avoiding the inefficiency of frequently reading small amounts of data.
1328
1329 If positive, the value is the number of milliseconds to sleep before
1330 reading the subprocess output.  If negative, the magnitude is the number
1331 of time slices to wait (effectively boosting the priority of the child
1332 process temporarily).  A value of zero disables waiting entirely.
1333 */ );
1334   Vwin32_pipe_read_delay = make_int (50);
1335
1336 #if 0
1337   DEFVAR_LISP ("win32-generate-fake-inodes", &Vwin32_generate_fake_inodes /*
1338     "Non-nil means attempt to fake realistic inode values.
1339 This works by hashing the truename of files, and should detect 
1340 aliasing between long and short (8.3 DOS) names, but can have
1341 false positives because of hash collisions.  Note that determing
1342 the truename of a file can be slow.
1343 */ );
1344   Vwin32_generate_fake_inodes = Qnil;
1345 #endif
1346 }
1347 /* end of ntproc.c */