gnus-art.el (gnus-article-add-buttons): Simplify condition.
[bpt/emacs.git] / src / w32proc.c
CommitLineData
e9e23e23 1/* Process support for GNU Emacs on the Microsoft W32 API.
9ec0b715 2 Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5df4f04c 3 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
6cdfb6e6 4
3b7ad313
EN
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
3b7ad313 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
3b7ad313
EN
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
6cdfb6e6 19
9ec0b715 20/*
6cdfb6e6
RS
21 Drew Bliss Oct 14, 1993
22 Adapted from alarm.c by Tim Fleehart
23*/
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <errno.h>
28#include <io.h>
c519b5e1 29#include <fcntl.h>
6cdfb6e6 30#include <signal.h>
51f635c4 31#include <sys/file.h>
d7306fe6 32#include <setjmp.h>
6cdfb6e6 33
c519b5e1 34/* must include CRT headers *before* config.h */
4838e624 35#include <config.h>
4838e624 36
c519b5e1
GV
37#undef signal
38#undef wait
39#undef spawnve
40#undef select
41#undef kill
42
6cdfb6e6 43#include <windows.h>
42c95ffb
AI
44#ifdef __GNUC__
45/* This definition is missing from mingw32 headers. */
ed3751c8 46extern BOOL WINAPI IsValidLocale (LCID, DWORD);
42c95ffb 47#endif
6cdfb6e6 48
d613418b
EZ
49#ifdef HAVE_LANGINFO_CODESET
50#include <nl_types.h>
51#include <langinfo.h>
52#endif
53
6cdfb6e6 54#include "lisp.h"
c949d9d0 55#include "character.h"
489f9371 56#include "w32.h"
b2fc9f3d 57#include "w32heap.h"
6cdfb6e6 58#include "systime.h"
3d7eead0
GV
59#include "syswait.h"
60#include "process.h"
e7c15bba 61#include "syssignal.h"
ef79fbba 62#include "w32term.h"
f481eb31 63#include "dispextern.h" /* for xstrcasecmp */
b23077df 64#include "coding.h"
3d7eead0 65
8747ac3f
EZ
66#define RVA_TO_PTR(var,section,filedata) \
67 ((void *)((section)->PointerToRawData \
68 + ((DWORD)(var) - (section)->VirtualAddress) \
69 + (filedata).file_base))
70
2fa4f090 71extern Lisp_Object Qlocal;
b2fc9f3d
GV
72
73Lisp_Object Qhigh, Qlow;
817abdf6 74
6cdfb6e6 75#ifdef EMACSDEBUG
b56ceb92
JB
76void
77_DebPrint (const char *fmt, ...)
6cdfb6e6 78{
c519b5e1 79 char buf[1024];
6cdfb6e6
RS
80 va_list args;
81
82 va_start (args, fmt);
83 vsprintf (buf, fmt, args);
84 va_end (args);
85 OutputDebugString (buf);
86}
87#endif
88
ed3751c8 89typedef void (_CALLBACK_ *signal_handler) (int);
6cdfb6e6
RS
90
91/* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
92static signal_handler sig_handlers[NSIG];
93
94/* Fake signal implementation to record the SIGCHLD handler. */
177c0ea7 95signal_handler
c519b5e1 96sys_signal (int sig, signal_handler handler)
6cdfb6e6
RS
97{
98 signal_handler old;
177c0ea7 99
6cdfb6e6
RS
100 if (sig != SIGCHLD)
101 {
102 errno = EINVAL;
103 return SIG_ERR;
104 }
105 old = sig_handlers[sig];
106 sig_handlers[sig] = handler;
107 return old;
108}
109
c519b5e1
GV
110/* Defined in <process.h> which conflicts with the local copy */
111#define _P_NOWAIT 1
112
113/* Child process management list. */
114int child_proc_count = 0;
115child_process child_procs[ MAX_CHILDREN ];
116child_process *dead_child = NULL;
117
24f981c9 118static DWORD WINAPI reader_thread (void *arg);
c519b5e1 119
6cdfb6e6 120/* Find an unused process slot. */
c519b5e1 121child_process *
6cdfb6e6
RS
122new_child (void)
123{
124 child_process *cp;
c519b5e1 125 DWORD id;
177c0ea7 126
9d4f32e8 127 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
6cdfb6e6 128 if (!CHILD_ACTIVE (cp))
c519b5e1
GV
129 goto Initialise;
130 if (child_proc_count == MAX_CHILDREN)
131 return NULL;
132 cp = &child_procs[child_proc_count++];
133
134 Initialise:
ed3751c8 135 memset (cp, 0, sizeof (*cp));
c519b5e1
GV
136 cp->fd = -1;
137 cp->pid = -1;
138 cp->procinfo.hProcess = NULL;
139 cp->status = STATUS_READ_ERROR;
140
141 /* use manual reset event so that select() will function properly */
142 cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
143 if (cp->char_avail)
144 {
145 cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
146 if (cp->char_consumed)
147 {
148 cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
149 if (cp->thrd)
150 return cp;
151 }
152 }
153 delete_child (cp);
154 return NULL;
155}
156
177c0ea7 157void
c519b5e1
GV
158delete_child (child_process *cp)
159{
160 int i;
161
162 /* Should not be deleting a child that is still needed. */
163 for (i = 0; i < MAXDESC; i++)
164 if (fd_info[i].cp == cp)
165 abort ();
166
167 if (!CHILD_ACTIVE (cp))
168 return;
169
170 /* reap thread if necessary */
171 if (cp->thrd)
172 {
173 DWORD rc;
174
175 if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE)
176 {
177 /* let the thread exit cleanly if possible */
178 cp->status = STATUS_READ_ERROR;
179 SetEvent (cp->char_consumed);
a017b515
JR
180#if 0
181 /* We used to forceably terminate the thread here, but it
182 is normally unnecessary, and in abnormal cases, the worst that
183 will happen is we have an extra idle thread hanging around
184 waiting for the zombie process. */
c519b5e1
GV
185 if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0)
186 {
187 DebPrint (("delete_child.WaitForSingleObject (thread) failed "
188 "with %lu for fd %ld\n", GetLastError (), cp->fd));
189 TerminateThread (cp->thrd, 0);
190 }
a017b515 191#endif
c519b5e1
GV
192 }
193 CloseHandle (cp->thrd);
194 cp->thrd = NULL;
195 }
196 if (cp->char_avail)
197 {
198 CloseHandle (cp->char_avail);
199 cp->char_avail = NULL;
200 }
201 if (cp->char_consumed)
202 {
203 CloseHandle (cp->char_consumed);
204 cp->char_consumed = NULL;
205 }
206
207 /* update child_proc_count (highest numbered slot in use plus one) */
208 if (cp == child_procs + child_proc_count - 1)
209 {
210 for (i = child_proc_count-1; i >= 0; i--)
211 if (CHILD_ACTIVE (&child_procs[i]))
212 {
213 child_proc_count = i + 1;
214 break;
215 }
216 }
217 if (i < 0)
218 child_proc_count = 0;
6cdfb6e6
RS
219}
220
221/* Find a child by pid. */
222static child_process *
223find_child_pid (DWORD pid)
224{
225 child_process *cp;
c519b5e1 226
9d4f32e8 227 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
6cdfb6e6
RS
228 if (CHILD_ACTIVE (cp) && pid == cp->pid)
229 return cp;
230 return NULL;
231}
232
6cdfb6e6 233
c519b5e1
GV
234/* Thread proc for child process and socket reader threads. Each thread
235 is normally blocked until woken by select() to check for input by
04bf5b65 236 reading one char. When the read completes, char_avail is signaled
c519b5e1 237 to wake up the select emulator and the thread blocks itself again. */
24f981c9 238static DWORD WINAPI
6cdfb6e6
RS
239reader_thread (void *arg)
240{
241 child_process *cp;
177c0ea7 242
6cdfb6e6
RS
243 /* Our identity */
244 cp = (child_process *)arg;
177c0ea7 245
6cdfb6e6 246 /* We have to wait for the go-ahead before we can start */
b2fc9f3d
GV
247 if (cp == NULL
248 || WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
c519b5e1
GV
249 return 1;
250
6cdfb6e6
RS
251 for (;;)
252 {
c519b5e1
GV
253 int rc;
254
f9125cde
KS
255 if (fd_info[cp->fd].flags & FILE_LISTEN)
256 rc = _sys_wait_accept (cp->fd);
257 else
258 rc = _sys_read_ahead (cp->fd);
c519b5e1
GV
259
260 /* The name char_avail is a misnomer - it really just means the
261 read-ahead has completed, whether successfully or not. */
6cdfb6e6
RS
262 if (!SetEvent (cp->char_avail))
263 {
264 DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
265 GetLastError (), cp->fd));
c519b5e1
GV
266 return 1;
267 }
268
269 if (rc == STATUS_READ_ERROR)
270 return 1;
177c0ea7 271
6cdfb6e6 272 /* If the read died, the child has died so let the thread die */
c519b5e1 273 if (rc == STATUS_READ_FAILED)
6cdfb6e6 274 break;
177c0ea7 275
6cdfb6e6
RS
276 /* Wait until our input is acknowledged before reading again */
277 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
278 {
279 DebPrint (("reader_thread.WaitForSingleObject failed with "
280 "%lu for fd %ld\n", GetLastError (), cp->fd));
281 break;
282 }
283 }
284 return 0;
285}
286
b2fc9f3d
GV
287/* To avoid Emacs changing directory, we just record here the directory
288 the new process should start in. This is set just before calling
289 sys_spawnve, and is not generally valid at any other time. */
290static char * process_dir;
291
177c0ea7 292static BOOL
a55a5f3c 293create_child (char *exe, char *cmdline, char *env, int is_gui_app,
c519b5e1 294 int * pPid, child_process *cp)
6cdfb6e6 295{
6cdfb6e6
RS
296 STARTUPINFO start;
297 SECURITY_ATTRIBUTES sec_attrs;
42c95ffb 298#if 0
6cdfb6e6 299 SECURITY_DESCRIPTOR sec_desc;
42c95ffb 300#endif
82e7c0a9 301 DWORD flags;
b2fc9f3d 302 char dir[ MAXPATHLEN ];
177c0ea7 303
c519b5e1 304 if (cp == NULL) abort ();
177c0ea7 305
6cdfb6e6
RS
306 memset (&start, 0, sizeof (start));
307 start.cb = sizeof (start);
177c0ea7 308
58d4e829 309#ifdef HAVE_NTGUI
a55a5f3c 310 if (NILP (Vw32_start_process_show_window) && !is_gui_app)
0ecf7d36
RS
311 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
312 else
313 start.dwFlags = STARTF_USESTDHANDLES;
58d4e829
GV
314 start.wShowWindow = SW_HIDE;
315
316 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
317 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
318 start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
319#endif /* HAVE_NTGUI */
320
42c95ffb 321#if 0
6cdfb6e6
RS
322 /* Explicitly specify no security */
323 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
c519b5e1 324 goto EH_Fail;
6cdfb6e6 325 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
c519b5e1 326 goto EH_Fail;
42c95ffb 327#endif
6cdfb6e6 328 sec_attrs.nLength = sizeof (sec_attrs);
42c95ffb 329 sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */;
6cdfb6e6 330 sec_attrs.bInheritHandle = FALSE;
177c0ea7 331
b2fc9f3d
GV
332 strcpy (dir, process_dir);
333 unixtodos_filename (dir);
82e7c0a9
AI
334
335 flags = (!NILP (Vw32_start_process_share_console)
336 ? CREATE_NEW_PROCESS_GROUP
337 : CREATE_NEW_CONSOLE);
338 if (NILP (Vw32_start_process_inherit_error_mode))
339 flags |= CREATE_DEFAULT_ERROR_MODE;
6cdfb6e6 340 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
82e7c0a9 341 flags, env, dir, &start, &cp->procinfo))
c519b5e1
GV
342 goto EH_Fail;
343
344 cp->pid = (int) cp->procinfo.dwProcessId;
345
346 /* Hack for Windows 95, which assigns large (ie negative) pids */
347 if (cp->pid < 0)
348 cp->pid = -cp->pid;
349
350 /* pid must fit in a Lisp_Int */
acba5cae 351 cp->pid = cp->pid & INTMASK;
c519b5e1 352
c519b5e1 353 *pPid = cp->pid;
b2fc9f3d 354
6cdfb6e6 355 return TRUE;
b2fc9f3d 356
6cdfb6e6 357 EH_Fail:
ed3751c8 358 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError ()););
6cdfb6e6
RS
359 return FALSE;
360}
361
362/* create_child doesn't know what emacs' file handle will be for waiting
363 on output from the child, so we need to make this additional call
364 to register the handle with the process
365 This way the select emulator knows how to match file handles with
366 entries in child_procs. */
177c0ea7 367void
6cdfb6e6
RS
368register_child (int pid, int fd)
369{
370 child_process *cp;
177c0ea7 371
6cdfb6e6
RS
372 cp = find_child_pid (pid);
373 if (cp == NULL)
374 {
375 DebPrint (("register_child unable to find pid %lu\n", pid));
376 return;
377 }
177c0ea7 378
6cdfb6e6
RS
379#ifdef FULL_DEBUG
380 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid));
381#endif
177c0ea7 382
6cdfb6e6 383 cp->fd = fd;
6cdfb6e6 384
c519b5e1
GV
385 /* thread is initially blocked until select is called; set status so
386 that select will release thread */
387 cp->status = STATUS_READ_ACKNOWLEDGED;
388
389 /* attach child_process to fd_info */
390 if (fd_info[fd].cp != NULL)
6cdfb6e6 391 {
c519b5e1
GV
392 DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd));
393 abort ();
6cdfb6e6 394 }
c519b5e1
GV
395
396 fd_info[fd].cp = cp;
6cdfb6e6
RS
397}
398
399/* When a process dies its pipe will break so the reader thread will
400 signal failure to the select emulator.
401 The select emulator then calls this routine to clean up.
402 Since the thread signaled failure we can assume it is exiting. */
177c0ea7 403static void
c519b5e1 404reap_subprocess (child_process *cp)
6cdfb6e6 405{
c519b5e1 406 if (cp->procinfo.hProcess)
6cdfb6e6 407 {
c519b5e1 408 /* Reap the process */
b2fc9f3d
GV
409#ifdef FULL_DEBUG
410 /* Process should have already died before we are called. */
411 if (WaitForSingleObject (cp->procinfo.hProcess, 0) != WAIT_OBJECT_0)
412 DebPrint (("reap_subprocess: child fpr fd %d has not died yet!", cp->fd));
413#endif
c519b5e1
GV
414 CloseHandle (cp->procinfo.hProcess);
415 cp->procinfo.hProcess = NULL;
416 CloseHandle (cp->procinfo.hThread);
417 cp->procinfo.hThread = NULL;
6cdfb6e6 418 }
c519b5e1
GV
419
420 /* For asynchronous children, the child_proc resources will be freed
421 when the last pipe read descriptor is closed; for synchronous
422 children, we must explicitly free the resources now because
423 register_child has not been called. */
424 if (cp->fd == -1)
425 delete_child (cp);
6cdfb6e6
RS
426}
427
428/* Wait for any of our existing child processes to die
429 When it does, close its handle
430 Return the pid and fill in the status if non-NULL. */
22759c72 431
177c0ea7 432int
c519b5e1 433sys_wait (int *status)
6cdfb6e6
RS
434{
435 DWORD active, retval;
436 int nh;
c519b5e1 437 int pid;
6cdfb6e6
RS
438 child_process *cp, *cps[MAX_CHILDREN];
439 HANDLE wait_hnd[MAX_CHILDREN];
177c0ea7 440
6cdfb6e6
RS
441 nh = 0;
442 if (dead_child != NULL)
443 {
444 /* We want to wait for a specific child */
c519b5e1 445 wait_hnd[nh] = dead_child->procinfo.hProcess;
6cdfb6e6 446 cps[nh] = dead_child;
c519b5e1 447 if (!wait_hnd[nh]) abort ();
6cdfb6e6 448 nh++;
b2fc9f3d
GV
449 active = 0;
450 goto get_result;
6cdfb6e6
RS
451 }
452 else
453 {
9d4f32e8 454 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
c519b5e1 455 /* some child_procs might be sockets; ignore them */
3ac04ed0
CY
456 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
457 && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
6cdfb6e6 458 {
c519b5e1 459 wait_hnd[nh] = cp->procinfo.hProcess;
6cdfb6e6
RS
460 cps[nh] = cp;
461 nh++;
462 }
463 }
177c0ea7 464
6cdfb6e6
RS
465 if (nh == 0)
466 {
467 /* Nothing to wait on, so fail */
468 errno = ECHILD;
469 return -1;
470 }
b2fc9f3d
GV
471
472 do
473 {
474 /* Check for quit about once a second. */
475 QUIT;
476 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000);
477 } while (active == WAIT_TIMEOUT);
478
6cdfb6e6
RS
479 if (active == WAIT_FAILED)
480 {
481 errno = EBADF;
482 return -1;
483 }
b2fc9f3d
GV
484 else if (active >= WAIT_OBJECT_0
485 && active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
6cdfb6e6
RS
486 {
487 active -= WAIT_OBJECT_0;
488 }
b2fc9f3d
GV
489 else if (active >= WAIT_ABANDONED_0
490 && active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
6cdfb6e6
RS
491 {
492 active -= WAIT_ABANDONED_0;
493 }
b2fc9f3d
GV
494 else
495 abort ();
496
497get_result:
6cdfb6e6
RS
498 if (!GetExitCodeProcess (wait_hnd[active], &retval))
499 {
500 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n",
501 GetLastError ()));
502 retval = 1;
503 }
504 if (retval == STILL_ACTIVE)
505 {
506 /* Should never happen */
507 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
508 errno = EINVAL;
509 return -1;
510 }
bc69349b
RS
511
512 /* Massage the exit code from the process to match the format expected
8e6208c5 513 by the WIFSTOPPED et al macros in syswait.h. Only WIFSIGNALED and
bc69349b
RS
514 WIFEXITED are supported; WIFSTOPPED doesn't make sense under NT. */
515
516 if (retval == STATUS_CONTROL_C_EXIT)
517 retval = SIGINT;
518 else
519 retval <<= 8;
177c0ea7 520
6cdfb6e6 521 cp = cps[active];
c519b5e1
GV
522 pid = cp->pid;
523#ifdef FULL_DEBUG
524 DebPrint (("Wait signaled with process pid %d\n", cp->pid));
525#endif
22759c72 526
6cdfb6e6
RS
527 if (status)
528 {
22759c72
KH
529 *status = retval;
530 }
531 else if (synch_process_alive)
532 {
533 synch_process_alive = 0;
22759c72 534
3d7eead0
GV
535 /* Report the status of the synchronous process. */
536 if (WIFEXITED (retval))
537 synch_process_retcode = WRETCODE (retval);
538 else if (WIFSIGNALED (retval))
539 {
540 int code = WTERMSIG (retval);
68c45bf0
PE
541 char *signame;
542
ca9c0567 543 synchronize_system_messages_locale ();
68c45bf0
PE
544 signame = strsignal (code);
545
3d7eead0
GV
546 if (signame == 0)
547 signame = "unknown";
548
549 synch_process_death = signame;
550 }
c519b5e1
GV
551
552 reap_subprocess (cp);
6cdfb6e6 553 }
b2fc9f3d
GV
554
555 reap_subprocess (cp);
177c0ea7 556
c519b5e1 557 return pid;
6cdfb6e6
RS
558}
559
75be5258
EZ
560/* Old versions of w32api headers don't have separate 32-bit and
561 64-bit defines, but the one they have matches the 32-bit variety. */
562#ifndef IMAGE_NT_OPTIONAL_HDR32_MAGIC
563# define IMAGE_NT_OPTIONAL_HDR32_MAGIC IMAGE_NT_OPTIONAL_HDR_MAGIC
564# define IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER
565#endif
566
24f981c9 567static void
b56ceb92
JB
568w32_executable_type (char * filename,
569 int * is_dos_app,
570 int * is_cygnus_app,
571 int * is_gui_app)
817abdf6 572{
b2fc9f3d
GV
573 file_data executable;
574 char * p;
177c0ea7 575
b2fc9f3d
GV
576 /* Default values in case we can't tell for sure. */
577 *is_dos_app = FALSE;
578 *is_cygnus_app = FALSE;
a55a5f3c 579 *is_gui_app = FALSE;
b2fc9f3d
GV
580
581 if (!open_input_file (&executable, filename))
582 return;
817abdf6 583
b2fc9f3d 584 p = strrchr (filename, '.');
177c0ea7 585
b2fc9f3d 586 /* We can only identify DOS .com programs from the extension. */
05131107 587 if (p && xstrcasecmp (p, ".com") == 0)
b2fc9f3d 588 *is_dos_app = TRUE;
05131107
JR
589 else if (p && (xstrcasecmp (p, ".bat") == 0
590 || xstrcasecmp (p, ".cmd") == 0))
b2fc9f3d
GV
591 {
592 /* A DOS shell script - it appears that CreateProcess is happy to
593 accept this (somewhat surprisingly); presumably it looks at
594 COMSPEC to determine what executable to actually invoke.
595 Therefore, we have to do the same here as well. */
596 /* Actually, I think it uses the program association for that
597 extension, which is defined in the registry. */
598 p = egetenv ("COMSPEC");
599 if (p)
a55a5f3c 600 w32_executable_type (p, is_dos_app, is_cygnus_app, is_gui_app);
b2fc9f3d
GV
601 }
602 else
817abdf6 603 {
b2fc9f3d
GV
604 /* Look for DOS .exe signature - if found, we must also check that
605 it isn't really a 16- or 32-bit Windows exe, since both formats
606 start with a DOS program stub. Note that 16-bit Windows
607 executables use the OS/2 1.x format. */
817abdf6 608
b2fc9f3d
GV
609 IMAGE_DOS_HEADER * dos_header;
610 IMAGE_NT_HEADERS * nt_header;
611
612 dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
613 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
614 goto unwind;
615
616 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
617
177c0ea7 618 if ((char *) nt_header > (char *) dos_header + executable.size)
817abdf6 619 {
b2fc9f3d
GV
620 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
621 *is_dos_app = TRUE;
177c0ea7 622 }
b2fc9f3d
GV
623 else if (nt_header->Signature != IMAGE_NT_SIGNATURE
624 && LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
625 {
626 *is_dos_app = TRUE;
627 }
628 else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
629 {
2b6e2f4d
JR
630 IMAGE_DATA_DIRECTORY *data_dir = NULL;
631 if (nt_header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
632 {
633 /* Ensure we are using the 32 bit structure. */
634 IMAGE_OPTIONAL_HEADER32 *opt
635 = (IMAGE_OPTIONAL_HEADER32*) &(nt_header->OptionalHeader);
636 data_dir = opt->DataDirectory;
637 *is_gui_app = (opt->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI);
638 }
639 /* MingW 3.12 has the required 64 bit structs, but in case older
640 versions don't, only check 64 bit exes if we know how. */
641#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC
642 else if (nt_header->OptionalHeader.Magic
643 == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
644 {
645 IMAGE_OPTIONAL_HEADER64 *opt
646 = (IMAGE_OPTIONAL_HEADER64*) &(nt_header->OptionalHeader);
647 data_dir = opt->DataDirectory;
648 *is_gui_app = (opt->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI);
649 }
650#endif
651 if (data_dir)
652 {
653 /* Look for cygwin.dll in DLL import list. */
654 IMAGE_DATA_DIRECTORY import_dir =
655 data_dir[IMAGE_DIRECTORY_ENTRY_IMPORT];
656 IMAGE_IMPORT_DESCRIPTOR * imports;
657 IMAGE_SECTION_HEADER * section;
658
659 section = rva_to_section (import_dir.VirtualAddress, nt_header);
660 imports = RVA_TO_PTR (import_dir.VirtualAddress, section,
661 executable);
662
663 for ( ; imports->Name; imports++)
664 {
665 char * dllname = RVA_TO_PTR (imports->Name, section,
666 executable);
35f36d65 667
2b6e2f4d
JR
668 /* The exact name of the cygwin dll has changed with
669 various releases, but hopefully this will be reasonably
670 future proof. */
671 if (strncmp (dllname, "cygwin", 6) == 0)
672 {
673 *is_cygnus_app = TRUE;
674 break;
675 }
676 }
677 }
b2fc9f3d 678 }
817abdf6 679 }
177c0ea7 680
b2fc9f3d
GV
681unwind:
682 close_file_data (&executable);
817abdf6
KH
683}
684
24f981c9 685static int
42c95ffb 686compare_env (const void *strp1, const void *strp2)
d9709fde 687{
42c95ffb 688 const char *str1 = *(const char **)strp1, *str2 = *(const char **)strp2;
d9709fde
GV
689
690 while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
691 {
11c22fff
AI
692 /* Sort order in command.com/cmd.exe is based on uppercasing
693 names, so do the same here. */
694 if (toupper (*str1) > toupper (*str2))
d9709fde 695 return 1;
11c22fff 696 else if (toupper (*str1) < toupper (*str2))
d9709fde
GV
697 return -1;
698 str1++, str2++;
699 }
700
701 if (*str1 == '=' && *str2 == '=')
702 return 0;
703 else if (*str1 == '=')
704 return -1;
705 else
706 return 1;
707}
708
24f981c9 709static void
d9709fde
GV
710merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
711{
712 char **optr, **nptr;
713 int num;
714
715 nptr = new_envp;
716 optr = envp1;
717 while (*optr)
718 *nptr++ = *optr++;
719 num = optr - envp1;
720
721 optr = envp2;
722 while (*optr)
723 *nptr++ = *optr++;
724 num += optr - envp2;
725
726 qsort (new_envp, num, sizeof (char *), compare_env);
727
728 *nptr = NULL;
729}
6cdfb6e6
RS
730
731/* When a new child process is created we need to register it in our list,
732 so intercept spawn requests. */
177c0ea7 733int
c519b5e1 734sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
6cdfb6e6 735{
0a4de642 736 Lisp_Object program, full;
6cdfb6e6 737 char *cmdline, *env, *parg, **targ;
d9709fde 738 int arglen, numenv;
c519b5e1
GV
739 int pid;
740 child_process *cp;
a55a5f3c 741 int is_dos_app, is_cygnus_app, is_gui_app;
b2fc9f3d
GV
742 int do_quoting = 0;
743 char escape_char;
d9709fde
GV
744 /* We pass our process ID to our children by setting up an environment
745 variable in their environment. */
746 char ppid_env_var_buffer[64];
747 char *extra_env[] = {ppid_env_var_buffer, NULL};
0a7a6051
JR
748 /* These are the characters that cause an argument to need quoting.
749 Arguments with whitespace characters need quoting to prevent the
750 argument being split into two or more. Arguments with wildcards
751 are also quoted, for consistency with posix platforms, where wildcards
752 are not expanded if we run the program directly without a shell.
753 Some extra whitespace characters need quoting in Cygwin programs,
754 so this list is conditionally modified below. */
755 char *sepchars = " \t*?";
d9709fde 756
c519b5e1
GV
757 /* We don't care about the other modes */
758 if (mode != _P_NOWAIT)
759 {
760 errno = EINVAL;
761 return -1;
762 }
0a4de642
RS
763
764 /* Handle executable names without an executable suffix. */
765 program = make_string (cmdname, strlen (cmdname));
766 if (NILP (Ffile_executable_p (program)))
767 {
768 struct gcpro gcpro1;
177c0ea7 769
0a4de642
RS
770 full = Qnil;
771 GCPRO1 (program);
44c7a526 772 openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK));
0a4de642
RS
773 UNGCPRO;
774 if (NILP (full))
775 {
776 errno = EINVAL;
777 return -1;
778 }
b2fc9f3d 779 program = full;
0a4de642
RS
780 }
781
b2fc9f3d 782 /* make sure argv[0] and cmdname are both in DOS format */
d5db4077 783 cmdname = SDATA (program);
c519b5e1
GV
784 unixtodos_filename (cmdname);
785 argv[0] = cmdname;
817abdf6 786
ef79fbba 787 /* Determine whether program is a 16-bit DOS executable, or a w32
b2fc9f3d
GV
788 executable that is implicitly linked to the Cygnus dll (implying it
789 was compiled with the Cygnus GNU toolchain and hence relies on
790 cygwin.dll to parse the command line - we use this to decide how to
a55a5f3c
AI
791 escape quote chars in command line args that must be quoted).
792
793 Also determine whether it is a GUI app, so that we don't hide its
794 initial window unless specifically requested. */
795 w32_executable_type (cmdname, &is_dos_app, &is_cygnus_app, &is_gui_app);
b2fc9f3d
GV
796
797 /* On Windows 95, if cmdname is a DOS app, we invoke a helper
798 application to start it by specifying the helper app as cmdname,
799 while leaving the real app name as argv[0]. */
800 if (is_dos_app)
817abdf6 801 {
b2fc9f3d
GV
802 cmdname = alloca (MAXPATHLEN);
803 if (egetenv ("CMDPROXY"))
804 strcpy (cmdname, egetenv ("CMDPROXY"));
805 else
806 {
d5db4077 807 strcpy (cmdname, SDATA (Vinvocation_directory));
b2fc9f3d
GV
808 strcat (cmdname, "cmdproxy.exe");
809 }
810 unixtodos_filename (cmdname);
817abdf6 811 }
177c0ea7 812
6cdfb6e6
RS
813 /* we have to do some conjuring here to put argv and envp into the
814 form CreateProcess wants... argv needs to be a space separated/null
815 terminated list of parameters, and envp is a null
816 separated/double-null terminated list of parameters.
c519b5e1 817
b2fc9f3d
GV
818 Additionally, zero-length args and args containing whitespace or
819 quote chars need to be wrapped in double quotes - for this to work,
820 embedded quotes need to be escaped as well. The aim is to ensure
821 the child process reconstructs the argv array we start with
822 exactly, so we treat quotes at the beginning and end of arguments
823 as embedded quotes.
824
ef79fbba 825 The w32 GNU-based library from Cygnus doubles quotes to escape
b2fc9f3d
GV
826 them, while MSVC uses backslash for escaping. (Actually the MSVC
827 startup code does attempt to recognise doubled quotes and accept
828 them, but gets it wrong and ends up requiring three quotes to get a
829 single embedded quote!) So by default we decide whether to use
830 quote or backslash as the escape character based on whether the
831 binary is apparently a Cygnus compiled app.
832
833 Note that using backslash to escape embedded quotes requires
834 additional special handling if an embedded quote is already
835 preceeded by backslash, or if an arg requiring quoting ends with
836 backslash. In such cases, the run of escape characters needs to be
837 doubled. For consistency, we apply this special handling as long
838 as the escape character is not quote.
839
840 Since we have no idea how large argv and envp are likely to be we
841 figure out list lengths on the fly and allocate them. */
842
843 if (!NILP (Vw32_quote_process_args))
844 {
845 do_quoting = 1;
846 /* Override escape char by binding w32-quote-process-args to
847 desired character, or use t for auto-selection. */
848 if (INTEGERP (Vw32_quote_process_args))
849 escape_char = XINT (Vw32_quote_process_args);
850 else
851 escape_char = is_cygnus_app ? '"' : '\\';
852 }
177c0ea7 853
9d4f32e8 854 /* Cygwin apps needs quoting a bit more often. */
dbb70029
GM
855 if (escape_char == '"')
856 sepchars = "\r\n\t\f '";
857
6cdfb6e6
RS
858 /* do argv... */
859 arglen = 0;
860 targ = argv;
861 while (*targ)
862 {
c519b5e1 863 char * p = *targ;
b2fc9f3d
GV
864 int need_quotes = 0;
865 int escape_char_run = 0;
c519b5e1
GV
866
867 if (*p == 0)
b2fc9f3d
GV
868 need_quotes = 1;
869 for ( ; *p; p++)
870 {
dbb70029
GM
871 if (escape_char == '"' && *p == '\\')
872 /* If it's a Cygwin app, \ needs to be escaped. */
873 arglen++;
874 else if (*p == '"')
b2fc9f3d
GV
875 {
876 /* allow for embedded quotes to be escaped */
877 arglen++;
878 need_quotes = 1;
879 /* handle the case where the embedded quote is already escaped */
880 if (escape_char_run > 0)
881 {
882 /* To preserve the arg exactly, we need to double the
883 preceding escape characters (plus adding one to
884 escape the quote character itself). */
885 arglen += escape_char_run;
886 }
887 }
dbb70029 888 else if (strchr (sepchars, *p) != NULL)
b2fc9f3d
GV
889 {
890 need_quotes = 1;
891 }
892
893 if (*p == escape_char && escape_char != '"')
894 escape_char_run++;
895 else
896 escape_char_run = 0;
897 }
898 if (need_quotes)
899 {
900 arglen += 2;
901 /* handle the case where the arg ends with an escape char - we
902 must not let the enclosing quote be escaped. */
903 if (escape_char_run > 0)
904 arglen += escape_char_run;
905 }
6cdfb6e6
RS
906 arglen += strlen (*targ++) + 1;
907 }
c519b5e1 908 cmdline = alloca (arglen);
6cdfb6e6
RS
909 targ = argv;
910 parg = cmdline;
911 while (*targ)
912 {
c519b5e1 913 char * p = *targ;
b2fc9f3d 914 int need_quotes = 0;
c519b5e1
GV
915
916 if (*p == 0)
b2fc9f3d 917 need_quotes = 1;
93fdf2f8 918
b2fc9f3d 919 if (do_quoting)
93fdf2f8 920 {
93fdf2f8 921 for ( ; *p; p++)
dbb70029 922 if ((strchr (sepchars, *p) != NULL) || *p == '"')
b2fc9f3d 923 need_quotes = 1;
93fdf2f8 924 }
b2fc9f3d 925 if (need_quotes)
c519b5e1 926 {
b2fc9f3d 927 int escape_char_run = 0;
c519b5e1
GV
928 char * first;
929 char * last;
930
931 p = *targ;
932 first = p;
933 last = p + strlen (p) - 1;
934 *parg++ = '"';
b2fc9f3d
GV
935#if 0
936 /* This version does not escape quotes if they occur at the
937 beginning or end of the arg - this could lead to incorrect
fffa137c 938 behavior when the arg itself represents a command line
b2fc9f3d
GV
939 containing quoted args. I believe this was originally done
940 as a hack to make some things work, before
941 `w32-quote-process-args' was added. */
c519b5e1
GV
942 while (*p)
943 {
944 if (*p == '"' && p > first && p < last)
b2fc9f3d 945 *parg++ = escape_char; /* escape embedded quotes */
c519b5e1
GV
946 *parg++ = *p++;
947 }
b2fc9f3d
GV
948#else
949 for ( ; *p; p++)
950 {
951 if (*p == '"')
952 {
953 /* double preceding escape chars if any */
954 while (escape_char_run > 0)
955 {
956 *parg++ = escape_char;
957 escape_char_run--;
958 }
959 /* escape all quote chars, even at beginning or end */
960 *parg++ = escape_char;
961 }
dbb70029
GM
962 else if (escape_char == '"' && *p == '\\')
963 *parg++ = '\\';
b2fc9f3d
GV
964 *parg++ = *p;
965
966 if (*p == escape_char && escape_char != '"')
967 escape_char_run++;
968 else
969 escape_char_run = 0;
970 }
971 /* double escape chars before enclosing quote */
972 while (escape_char_run > 0)
973 {
974 *parg++ = escape_char;
975 escape_char_run--;
976 }
977#endif
c519b5e1
GV
978 *parg++ = '"';
979 }
980 else
981 {
982 strcpy (parg, *targ);
983 parg += strlen (*targ);
984 }
6cdfb6e6 985 *parg++ = ' ';
c519b5e1 986 targ++;
6cdfb6e6
RS
987 }
988 *--parg = '\0';
177c0ea7 989
6cdfb6e6
RS
990 /* and envp... */
991 arglen = 1;
992 targ = envp;
d9709fde 993 numenv = 1; /* for end null */
6cdfb6e6
RS
994 while (*targ)
995 {
996 arglen += strlen (*targ++) + 1;
d9709fde 997 numenv++;
6cdfb6e6 998 }
d9709fde 999 /* extra env vars... */
177c0ea7 1000 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d",
6cdfb6e6
RS
1001 GetCurrentProcessId ());
1002 arglen += strlen (ppid_env_var_buffer) + 1;
d9709fde 1003 numenv++;
6cdfb6e6 1004
d9709fde
GV
1005 /* merge env passed in and extra env into one, and sort it. */
1006 targ = (char **) alloca (numenv * sizeof (char *));
1007 merge_and_sort_env (envp, extra_env, targ);
1008
1009 /* concatenate env entries. */
c519b5e1 1010 env = alloca (arglen);
6cdfb6e6
RS
1011 parg = env;
1012 while (*targ)
1013 {
1014 strcpy (parg, *targ);
1015 parg += strlen (*targ++);
1016 *parg++ = '\0';
1017 }
6cdfb6e6
RS
1018 *parg++ = '\0';
1019 *parg = '\0';
c519b5e1
GV
1020
1021 cp = new_child ();
1022 if (cp == NULL)
1023 {
1024 errno = EAGAIN;
1025 return -1;
1026 }
177c0ea7 1027
6cdfb6e6 1028 /* Now create the process. */
a55a5f3c 1029 if (!create_child (cmdname, cmdline, env, is_gui_app, &pid, cp))
6cdfb6e6 1030 {
c519b5e1 1031 delete_child (cp);
6cdfb6e6 1032 errno = ENOEXEC;
c519b5e1 1033 return -1;
6cdfb6e6 1034 }
177c0ea7 1035
c519b5e1 1036 return pid;
6cdfb6e6
RS
1037}
1038
1039/* Emulate the select call
1040 Wait for available input on any of the given rfds, or timeout if
1041 a timeout is given and no input is detected
b2fc9f3d
GV
1042 wfds and efds are not supported and must be NULL.
1043
1044 For simplicity, we detect the death of child processes here and
1045 synchronously call the SIGCHLD handler. Since it is possible for
1046 children to be created without a corresponding pipe handle from which
1047 to read output, we wait separately on the process handles as well as
1048 the char_avail events for each process pipe. We only call
86143765
RS
1049 wait/reap_process when the process actually terminates.
1050
1051 To reduce the number of places in which Emacs can be hung such that
1052 C-g is not able to interrupt it, we always wait on interrupt_handle
04bf5b65 1053 (which is signaled by the input thread when C-g is detected). If we
86143765
RS
1054 detect that we were woken up by C-g, we return -1 with errno set to
1055 EINTR as on Unix. */
6cdfb6e6
RS
1056
1057/* From ntterm.c */
1058extern HANDLE keyboard_handle;
86143765
RS
1059
1060/* From w32xfns.c */
1061extern HANDLE interrupt_handle;
1062
6cdfb6e6
RS
1063/* From process.c */
1064extern int proc_buffered_char[];
1065
177c0ea7 1066int
22759c72
KH
1067sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1068 EMACS_TIME *timeout)
6cdfb6e6
RS
1069{
1070 SELECT_TYPE orfds;
b2fc9f3d
GV
1071 DWORD timeout_ms, start_time;
1072 int i, nh, nc, nr;
6cdfb6e6 1073 DWORD active;
b2fc9f3d
GV
1074 child_process *cp, *cps[MAX_CHILDREN];
1075 HANDLE wait_hnd[MAXDESC + MAX_CHILDREN];
c519b5e1 1076 int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */
177c0ea7 1077
b2fc9f3d
GV
1078 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE;
1079
6cdfb6e6 1080 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
177c0ea7 1081 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL)
6cdfb6e6 1082 {
b2fc9f3d 1083 Sleep (timeout_ms);
6cdfb6e6
RS
1084 return 0;
1085 }
1086
1087 /* Otherwise, we only handle rfds, so fail otherwise. */
1088 if (rfds == NULL || wfds != NULL || efds != NULL)
1089 {
1090 errno = EINVAL;
1091 return -1;
1092 }
177c0ea7 1093
6cdfb6e6
RS
1094 orfds = *rfds;
1095 FD_ZERO (rfds);
1096 nr = 0;
86143765
RS
1097
1098 /* Always wait on interrupt_handle, to detect C-g (quit). */
1099 wait_hnd[0] = interrupt_handle;
1100 fdindex[0] = -1;
177c0ea7 1101
b2fc9f3d 1102 /* Build a list of pipe handles to wait on. */
86143765 1103 nh = 1;
6cdfb6e6
RS
1104 for (i = 0; i < nfds; i++)
1105 if (FD_ISSET (i, &orfds))
1106 {
1107 if (i == 0)
1108 {
c519b5e1
GV
1109 if (keyboard_handle)
1110 {
1111 /* Handle stdin specially */
1112 wait_hnd[nh] = keyboard_handle;
1113 fdindex[nh] = i;
1114 nh++;
1115 }
6cdfb6e6
RS
1116
1117 /* Check for any emacs-generated input in the queue since
1118 it won't be detected in the wait */
1119 if (detect_input_pending ())
1120 {
1121 FD_SET (i, rfds);
c519b5e1 1122 return 1;
6cdfb6e6
RS
1123 }
1124 }
1125 else
1126 {
c519b5e1
GV
1127 /* Child process and socket input */
1128 cp = fd_info[i].cp;
6cdfb6e6
RS
1129 if (cp)
1130 {
c519b5e1
GV
1131 int current_status = cp->status;
1132
1133 if (current_status == STATUS_READ_ACKNOWLEDGED)
1134 {
1135 /* Tell reader thread which file handle to use. */
1136 cp->fd = i;
1137 /* Wake up the reader thread for this process */
1138 cp->status = STATUS_READ_READY;
1139 if (!SetEvent (cp->char_consumed))
1140 DebPrint (("nt_select.SetEvent failed with "
1141 "%lu for fd %ld\n", GetLastError (), i));
1142 }
1143
1144#ifdef CHECK_INTERLOCK
1145 /* slightly crude cross-checking of interlock between threads */
1146
1147 current_status = cp->status;
1148 if (WaitForSingleObject (cp->char_avail, 0) == WAIT_OBJECT_0)
1149 {
04bf5b65 1150 /* char_avail has been signaled, so status (which may
c519b5e1
GV
1151 have changed) should indicate read has completed
1152 but has not been acknowledged. */
1153 current_status = cp->status;
b2fc9f3d
GV
1154 if (current_status != STATUS_READ_SUCCEEDED
1155 && current_status != STATUS_READ_FAILED)
c519b5e1
GV
1156 DebPrint (("char_avail set, but read not completed: status %d\n",
1157 current_status));
1158 }
1159 else
1160 {
04bf5b65 1161 /* char_avail has not been signaled, so status should
c519b5e1 1162 indicate that read is in progress; small possibility
04bf5b65 1163 that read has completed but event wasn't yet signaled
c519b5e1
GV
1164 when we tested it (because a context switch occurred
1165 or if running on separate CPUs). */
b2fc9f3d
GV
1166 if (current_status != STATUS_READ_READY
1167 && current_status != STATUS_READ_IN_PROGRESS
1168 && current_status != STATUS_READ_SUCCEEDED
1169 && current_status != STATUS_READ_FAILED)
c519b5e1
GV
1170 DebPrint (("char_avail reset, but read status is bad: %d\n",
1171 current_status));
1172 }
1173#endif
1174 wait_hnd[nh] = cp->char_avail;
1175 fdindex[nh] = i;
1176 if (!wait_hnd[nh]) abort ();
1177 nh++;
6cdfb6e6
RS
1178#ifdef FULL_DEBUG
1179 DebPrint (("select waiting on child %d fd %d\n",
1180 cp-child_procs, i));
1181#endif
6cdfb6e6
RS
1182 }
1183 else
1184 {
c519b5e1 1185 /* Unable to find something to wait on for this fd, skip */
ef79fbba
GV
1186
1187 /* Note that this is not a fatal error, and can in fact
1188 happen in unusual circumstances. Specifically, if
1189 sys_spawnve fails, eg. because the program doesn't
1190 exist, and debug-on-error is t so Fsignal invokes a
1191 nested input loop, then the process output pipe is
1192 still included in input_wait_mask with no child_proc
1193 associated with it. (It is removed when the debugger
1194 exits the nested input loop and the error is thrown.) */
1195
c519b5e1 1196 DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i));
6cdfb6e6
RS
1197 }
1198 }
1199 }
b2fc9f3d
GV
1200
1201count_children:
1202 /* Add handles of child processes. */
1203 nc = 0;
9d4f32e8 1204 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
ef79fbba
GV
1205 /* Some child_procs might be sockets; ignore them. Also some
1206 children may have died already, but we haven't finished reading
1207 the process output; ignore them too. */
1208 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
1209 && (cp->fd < 0
1210 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0
1211 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
1212 )
b2fc9f3d
GV
1213 {
1214 wait_hnd[nh + nc] = cp->procinfo.hProcess;
1215 cps[nc] = cp;
1216 nc++;
1217 }
177c0ea7 1218
6cdfb6e6 1219 /* Nothing to look for, so we didn't find anything */
177c0ea7 1220 if (nh + nc == 0)
6cdfb6e6 1221 {
22759c72 1222 if (timeout)
b2fc9f3d 1223 Sleep (timeout_ms);
6cdfb6e6
RS
1224 return 0;
1225 }
177c0ea7 1226
b2fc9f3d 1227 start_time = GetTickCount ();
8b031dcc 1228
04bf5b65 1229 /* Wait for input or child death to be signaled. If user input is
8b031dcc
AI
1230 allowed, then also accept window messages. */
1231 if (FD_ISSET (0, &orfds))
1232 active = MsgWaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms,
1233 QS_ALLINPUT);
1234 else
1235 active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms);
c519b5e1 1236
6cdfb6e6
RS
1237 if (active == WAIT_FAILED)
1238 {
1239 DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
b2fc9f3d 1240 nh + nc, timeout_ms, GetLastError ()));
d64b707c 1241 /* don't return EBADF - this causes wait_reading_process_output to
c519b5e1
GV
1242 abort; WAIT_FAILED is returned when single-stepping under
1243 Windows 95 after switching thread focus in debugger, and
1244 possibly at other times. */
1245 errno = EINTR;
6cdfb6e6
RS
1246 return -1;
1247 }
1248 else if (active == WAIT_TIMEOUT)
1249 {
1250 return 0;
1251 }
b2fc9f3d
GV
1252 else if (active >= WAIT_OBJECT_0
1253 && active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
6cdfb6e6
RS
1254 {
1255 active -= WAIT_OBJECT_0;
1256 }
b2fc9f3d
GV
1257 else if (active >= WAIT_ABANDONED_0
1258 && active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
6cdfb6e6
RS
1259 {
1260 active -= WAIT_ABANDONED_0;
1261 }
b2fc9f3d
GV
1262 else
1263 abort ();
6cdfb6e6 1264
c519b5e1 1265 /* Loop over all handles after active (now officially documented as
04bf5b65 1266 being the first signaled handle in the array). We do this to
c519b5e1
GV
1267 ensure fairness, so that all channels with data available will be
1268 processed - otherwise higher numbered channels could be starved. */
1269 do
6cdfb6e6 1270 {
8b031dcc
AI
1271 if (active == nh + nc)
1272 {
1273 /* There are messages in the lisp thread's queue; we must
1274 drain the queue now to ensure they are processed promptly,
1275 because if we don't do so, we will not be woken again until
1276 further messages arrive.
1277
1278 NB. If ever we allow window message procedures to callback
1279 into lisp, we will need to ensure messages are dispatched
1280 at a safe time for lisp code to be run (*), and we may also
1281 want to provide some hooks in the dispatch loop to cater
1282 for modeless dialogs created by lisp (ie. to register
1283 window handles to pass to IsDialogMessage).
1284
1285 (*) Note that MsgWaitForMultipleObjects above is an
1286 internal dispatch point for messages that are sent to
1287 windows created by this thread. */
1288 drain_message_queue ();
1289 }
1290 else if (active >= nh)
b2fc9f3d
GV
1291 {
1292 cp = cps[active - nh];
ef79fbba
GV
1293
1294 /* We cannot always signal SIGCHLD immediately; if we have not
1295 finished reading the process output, we must delay sending
1296 SIGCHLD until we do. */
1297
1298 if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0)
1299 fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD;
b2fc9f3d 1300 /* SIG_DFL for SIGCHLD is ignore */
ef79fbba
GV
1301 else if (sig_handlers[SIGCHLD] != SIG_DFL &&
1302 sig_handlers[SIGCHLD] != SIG_IGN)
b2fc9f3d
GV
1303 {
1304#ifdef FULL_DEBUG
1305 DebPrint (("select calling SIGCHLD handler for pid %d\n",
1306 cp->pid));
1307#endif
1308 dead_child = cp;
1309 sig_handlers[SIGCHLD] (SIGCHLD);
1310 dead_child = NULL;
1311 }
1312 }
86143765
RS
1313 else if (fdindex[active] == -1)
1314 {
1315 /* Quit (C-g) was detected. */
1316 errno = EINTR;
1317 return -1;
1318 }
b2fc9f3d 1319 else if (fdindex[active] == 0)
c519b5e1
GV
1320 {
1321 /* Keyboard input available */
1322 FD_SET (0, rfds);
6cdfb6e6 1323 nr++;
c519b5e1 1324 }
6cdfb6e6 1325 else
c519b5e1 1326 {
b2fc9f3d
GV
1327 /* must be a socket or pipe - read ahead should have
1328 completed, either succeeding or failing. */
c519b5e1
GV
1329 FD_SET (fdindex[active], rfds);
1330 nr++;
c519b5e1
GV
1331 }
1332
b2fc9f3d
GV
1333 /* Even though wait_reading_process_output only reads from at most
1334 one channel, we must process all channels here so that we reap
1335 all children that have died. */
1336 while (++active < nh + nc)
c519b5e1
GV
1337 if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0)
1338 break;
b2fc9f3d
GV
1339 } while (active < nh + nc);
1340
1341 /* If no input has arrived and timeout hasn't expired, wait again. */
1342 if (nr == 0)
1343 {
1344 DWORD elapsed = GetTickCount () - start_time;
1345
1346 if (timeout_ms > elapsed) /* INFINITE is MAX_UINT */
1347 {
1348 if (timeout_ms != INFINITE)
1349 timeout_ms -= elapsed;
1350 goto count_children;
1351 }
1352 }
c519b5e1 1353
6cdfb6e6
RS
1354 return nr;
1355}
1356
c519b5e1 1357/* Substitute for certain kill () operations */
b2fc9f3d
GV
1358
1359static BOOL CALLBACK
42c95ffb 1360find_child_console (HWND hwnd, LPARAM arg)
b2fc9f3d 1361{
42c95ffb 1362 child_process * cp = (child_process *) arg;
b2fc9f3d
GV
1363 DWORD thread_id;
1364 DWORD process_id;
1365
1366 thread_id = GetWindowThreadProcessId (hwnd, &process_id);
1367 if (process_id == cp->procinfo.dwProcessId)
1368 {
1369 char window_class[32];
1370
1371 GetClassName (hwnd, window_class, sizeof (window_class));
1372 if (strcmp (window_class,
1373 (os_subtype == OS_WIN95)
1374 ? "tty"
1375 : "ConsoleWindowClass") == 0)
1376 {
1377 cp->hwnd = hwnd;
1378 return FALSE;
1379 }
1380 }
1381 /* keep looking */
1382 return TRUE;
1383}
1384
177c0ea7 1385int
c519b5e1 1386sys_kill (int pid, int sig)
6cdfb6e6
RS
1387{
1388 child_process *cp;
c519b5e1
GV
1389 HANDLE proc_hand;
1390 int need_to_free = 0;
1391 int rc = 0;
177c0ea7 1392
6cdfb6e6
RS
1393 /* Only handle signals that will result in the process dying */
1394 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
1395 {
1396 errno = EINVAL;
1397 return -1;
1398 }
c519b5e1 1399
6cdfb6e6
RS
1400 cp = find_child_pid (pid);
1401 if (cp == NULL)
1402 {
c519b5e1
GV
1403 proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
1404 if (proc_hand == NULL)
1405 {
1406 errno = EPERM;
1407 return -1;
1408 }
1409 need_to_free = 1;
1410 }
1411 else
1412 {
1413 proc_hand = cp->procinfo.hProcess;
1414 pid = cp->procinfo.dwProcessId;
b2fc9f3d
GV
1415
1416 /* Try to locate console window for process. */
1417 EnumWindows (find_child_console, (LPARAM) cp);
6cdfb6e6 1418 }
177c0ea7 1419
a55a5f3c 1420 if (sig == SIGINT || sig == SIGQUIT)
6cdfb6e6 1421 {
b2fc9f3d
GV
1422 if (NILP (Vw32_start_process_share_console) && cp && cp->hwnd)
1423 {
1424 BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
a55a5f3c
AI
1425 /* Fake Ctrl-C for SIGINT, and Ctrl-Break for SIGQUIT. */
1426 BYTE vk_break_code = (sig == SIGINT) ? 'C' : VK_CANCEL;
b2fc9f3d
GV
1427 BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
1428 HWND foreground_window;
1429
1430 if (break_scan_code == 0)
1431 {
a55a5f3c 1432 /* Fake Ctrl-C for SIGQUIT if we can't manage Ctrl-Break. */
b2fc9f3d
GV
1433 vk_break_code = 'C';
1434 break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
1435 }
1436
1437 foreground_window = GetForegroundWindow ();
f446016f 1438 if (foreground_window)
b2fc9f3d 1439 {
f446016f
AI
1440 /* NT 5.0, and apparently also Windows 98, will not allow
1441 a Window to be set to foreground directly without the
1442 user's involvement. The workaround is to attach
1443 ourselves to the thread that owns the foreground
1444 window, since that is the only thread that can set the
1445 foreground window. */
1446 DWORD foreground_thread, child_thread;
1447 foreground_thread =
1448 GetWindowThreadProcessId (foreground_window, NULL);
1449 if (foreground_thread == GetCurrentThreadId ()
1450 || !AttachThreadInput (GetCurrentThreadId (),
1451 foreground_thread, TRUE))
1452 foreground_thread = 0;
1453
1454 child_thread = GetWindowThreadProcessId (cp->hwnd, NULL);
1455 if (child_thread == GetCurrentThreadId ()
1456 || !AttachThreadInput (GetCurrentThreadId (),
1457 child_thread, TRUE))
1458 child_thread = 0;
1459
1460 /* Set the foreground window to the child. */
1461 if (SetForegroundWindow (cp->hwnd))
1462 {
1463 /* Generate keystrokes as if user had typed Ctrl-Break or
1464 Ctrl-C. */
1465 keybd_event (VK_CONTROL, control_scan_code, 0, 0);
1466 keybd_event (vk_break_code, break_scan_code,
1467 (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
1468 keybd_event (vk_break_code, break_scan_code,
1469 (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
1470 | KEYEVENTF_KEYUP, 0);
1471 keybd_event (VK_CONTROL, control_scan_code,
1472 KEYEVENTF_KEYUP, 0);
1473
1474 /* Sleep for a bit to give time for Emacs frame to respond
1475 to focus change events (if Emacs was active app). */
1476 Sleep (100);
1477
1478 SetForegroundWindow (foreground_window);
1479 }
1480 /* Detach from the foreground and child threads now that
1481 the foreground switching is over. */
1482 if (foreground_thread)
1483 AttachThreadInput (GetCurrentThreadId (),
1484 foreground_thread, FALSE);
1485 if (child_thread)
1486 AttachThreadInput (GetCurrentThreadId (),
1487 child_thread, FALSE);
1488 }
1489 }
c519b5e1 1490 /* Ctrl-Break is NT equivalent of SIGINT. */
b2fc9f3d 1491 else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
6cdfb6e6 1492 {
c519b5e1 1493 DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
6cdfb6e6
RS
1494 "for pid %lu\n", GetLastError (), pid));
1495 errno = EINVAL;
c519b5e1 1496 rc = -1;
80874ef7 1497 }
6cdfb6e6
RS
1498 }
1499 else
1500 {
b2fc9f3d
GV
1501 if (NILP (Vw32_start_process_share_console) && cp && cp->hwnd)
1502 {
1503#if 1
1504 if (os_subtype == OS_WIN95)
1505 {
1506/*
1507 Another possibility is to try terminating the VDM out-right by
1508 calling the Shell VxD (id 0x17) V86 interface, function #4
1509 "SHELL_Destroy_VM", ie.
1510
1511 mov edx,4
1512 mov ebx,vm_handle
1513 call shellapi
1514
1515 First need to determine the current VM handle, and then arrange for
1516 the shellapi call to be made from the system vm (by using
1517 Switch_VM_and_callback).
1518
1519 Could try to invoke DestroyVM through CallVxD.
1520
1521*/
ef79fbba
GV
1522#if 0
1523 /* On Win95, posting WM_QUIT causes the 16-bit subsystem
1524 to hang when cmdproxy is used in conjunction with
1525 command.com for an interactive shell. Posting
1526 WM_CLOSE pops up a dialog that, when Yes is selected,
1527 does the same thing. TerminateProcess is also less
1528 than ideal in that subprocesses tend to stick around
1529 until the machine is shutdown, but at least it
1530 doesn't freeze the 16-bit subsystem. */
b2fc9f3d 1531 PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
ef79fbba
GV
1532#endif
1533 if (!TerminateProcess (proc_hand, 0xff))
1534 {
1535 DebPrint (("sys_kill.TerminateProcess returned %d "
1536 "for pid %lu\n", GetLastError (), pid));
1537 errno = EINVAL;
1538 rc = -1;
1539 }
b2fc9f3d
GV
1540 }
1541 else
1542#endif
1543 PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
1544 }
fbd6baed 1545 /* Kill the process. On W32 this doesn't kill child processes
8eae7766 1546 so it doesn't work very well for shells which is why it's not
b2fc9f3d
GV
1547 used in every case. */
1548 else if (!TerminateProcess (proc_hand, 0xff))
6cdfb6e6 1549 {
c519b5e1 1550 DebPrint (("sys_kill.TerminateProcess returned %d "
6cdfb6e6
RS
1551 "for pid %lu\n", GetLastError (), pid));
1552 errno = EINVAL;
c519b5e1 1553 rc = -1;
6cdfb6e6
RS
1554 }
1555 }
c519b5e1
GV
1556
1557 if (need_to_free)
1558 CloseHandle (proc_hand);
1559
1560 return rc;
6cdfb6e6
RS
1561}
1562
09522567 1563/* extern int report_file_error (char *, Lisp_Object); */
c519b5e1
GV
1564
1565/* The following two routines are used to manipulate stdin, stdout, and
1566 stderr of our child processes.
1567
1568 Assuming that in, out, and err are *not* inheritable, we make them
1569 stdin, stdout, and stderr of the child as follows:
1570
1571 - Save the parent's current standard handles.
1572 - Set the std handles to inheritable duplicates of the ones being passed in.
1573 (Note that _get_osfhandle() is an io.h procedure that retrieves the
1574 NT file handle for a crt file descriptor.)
1575 - Spawn the child, which inherits in, out, and err as stdin,
1576 stdout, and stderr. (see Spawnve)
1577 - Close the std handles passed to the child.
1578 - Reset the parent's standard handles to the saved handles.
1579 (see reset_standard_handles)
1580 We assume that the caller closes in, out, and err after calling us. */
1581
1582void
1583prepare_standard_handles (int in, int out, int err, HANDLE handles[3])
6cdfb6e6 1584{
c519b5e1
GV
1585 HANDLE parent;
1586 HANDLE newstdin, newstdout, newstderr;
1587
1588 parent = GetCurrentProcess ();
1589
1590 handles[0] = GetStdHandle (STD_INPUT_HANDLE);
1591 handles[1] = GetStdHandle (STD_OUTPUT_HANDLE);
1592 handles[2] = GetStdHandle (STD_ERROR_HANDLE);
1593
1594 /* make inheritable copies of the new handles */
177c0ea7 1595 if (!DuplicateHandle (parent,
c519b5e1
GV
1596 (HANDLE) _get_osfhandle (in),
1597 parent,
177c0ea7
JB
1598 &newstdin,
1599 0,
1600 TRUE,
c519b5e1
GV
1601 DUPLICATE_SAME_ACCESS))
1602 report_file_error ("Duplicating input handle for child", Qnil);
177c0ea7 1603
c519b5e1
GV
1604 if (!DuplicateHandle (parent,
1605 (HANDLE) _get_osfhandle (out),
1606 parent,
1607 &newstdout,
1608 0,
1609 TRUE,
1610 DUPLICATE_SAME_ACCESS))
1611 report_file_error ("Duplicating output handle for child", Qnil);
177c0ea7 1612
c519b5e1
GV
1613 if (!DuplicateHandle (parent,
1614 (HANDLE) _get_osfhandle (err),
1615 parent,
1616 &newstderr,
1617 0,
1618 TRUE,
1619 DUPLICATE_SAME_ACCESS))
1620 report_file_error ("Duplicating error handle for child", Qnil);
1621
1622 /* and store them as our std handles */
1623 if (!SetStdHandle (STD_INPUT_HANDLE, newstdin))
1624 report_file_error ("Changing stdin handle", Qnil);
177c0ea7 1625
c519b5e1
GV
1626 if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout))
1627 report_file_error ("Changing stdout handle", Qnil);
1628
1629 if (!SetStdHandle (STD_ERROR_HANDLE, newstderr))
1630 report_file_error ("Changing stderr handle", Qnil);
1631}
1632
1633void
1634reset_standard_handles (int in, int out, int err, HANDLE handles[3])
1635{
1636 /* close the duplicated handles passed to the child */
1637 CloseHandle (GetStdHandle (STD_INPUT_HANDLE));
1638 CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE));
1639 CloseHandle (GetStdHandle (STD_ERROR_HANDLE));
1640
1641 /* now restore parent's saved std handles */
1642 SetStdHandle (STD_INPUT_HANDLE, handles[0]);
1643 SetStdHandle (STD_OUTPUT_HANDLE, handles[1]);
1644 SetStdHandle (STD_ERROR_HANDLE, handles[2]);
6cdfb6e6 1645}
c519b5e1 1646
b2fc9f3d
GV
1647void
1648set_process_dir (char * dir)
1649{
1650 process_dir = dir;
1651}
1652
a11e68d0
RS
1653/* To avoid problems with winsock implementations that work over dial-up
1654 connections causing or requiring a connection to exist while Emacs is
1655 running, Emacs no longer automatically loads winsock on startup if it
1656 is present. Instead, it will be loaded when open-network-stream is
1657 first called.
1658
1659 To allow full control over when winsock is loaded, we provide these
1660 two functions to dynamically load and unload winsock. This allows
1661 dial-up users to only be connected when they actually need to use
1662 socket services. */
1663
1664/* From nt.c */
1665extern HANDLE winsock_lib;
1666extern BOOL term_winsock (void);
1667extern BOOL init_winsock (int load_now);
1668
fbd6baed 1669DEFUN ("w32-has-winsock", Fw32_has_winsock, Sw32_has_winsock, 0, 1, 0,
33f09670
JR
1670 doc: /* Test for presence of the Windows socket library `winsock'.
1671Returns non-nil if winsock support is present, nil otherwise.
1672
1673If the optional argument LOAD-NOW is non-nil, the winsock library is
1674also loaded immediately if not already loaded. If winsock is loaded,
1675the winsock local hostname is returned (since this may be different from
1676the value of `system-name' and should supplant it), otherwise t is
1677returned to indicate winsock support is present. */)
5842a27b 1678 (Lisp_Object load_now)
a11e68d0
RS
1679{
1680 int have_winsock;
1681
1682 have_winsock = init_winsock (!NILP (load_now));
1683 if (have_winsock)
1684 {
1685 if (winsock_lib != NULL)
1686 {
1687 /* Return new value for system-name. The best way to do this
1688 is to call init_system_name, saving and restoring the
1689 original value to avoid side-effects. */
1690 Lisp_Object orig_hostname = Vsystem_name;
1691 Lisp_Object hostname;
1692
1693 init_system_name ();
1694 hostname = Vsystem_name;
1695 Vsystem_name = orig_hostname;
1696 return hostname;
1697 }
1698 return Qt;
1699 }
1700 return Qnil;
1701}
1702
fbd6baed 1703DEFUN ("w32-unload-winsock", Fw32_unload_winsock, Sw32_unload_winsock,
a11e68d0 1704 0, 0, 0,
33f09670
JR
1705 doc: /* Unload the Windows socket library `winsock' if loaded.
1706This is provided to allow dial-up socket connections to be disconnected
1707when no longer needed. Returns nil without unloading winsock if any
1708socket connections still exist. */)
5842a27b 1709 (void)
a11e68d0
RS
1710{
1711 return term_winsock () ? Qt : Qnil;
1712}
1713
93fdf2f8 1714\f
b2fc9f3d
GV
1715/* Some miscellaneous functions that are Windows specific, but not GUI
1716 specific (ie. are applicable in terminal or batch mode as well). */
1717
b2fc9f3d 1718DEFUN ("w32-short-file-name", Fw32_short_file_name, Sw32_short_file_name, 1, 1, 0,
33f09670
JR
1719 doc: /* Return the short file name version (8.3) of the full path of FILENAME.
1720If FILENAME does not exist, return nil.
1721All path elements in FILENAME are converted to their short names. */)
5842a27b 1722 (Lisp_Object filename)
b2fc9f3d
GV
1723{
1724 char shortname[MAX_PATH];
1725
b7826503 1726 CHECK_STRING (filename);
b2fc9f3d
GV
1727
1728 /* first expand it. */
1729 filename = Fexpand_file_name (filename, Qnil);
1730
1731 /* luckily, this returns the short version of each element in the path. */
b23077df 1732 if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
b2fc9f3d
GV
1733 return Qnil;
1734
087fc47a 1735 dostounix_filename (shortname);
b2fc9f3d
GV
1736
1737 return build_string (shortname);
1738}
1739
1740
1741DEFUN ("w32-long-file-name", Fw32_long_file_name, Sw32_long_file_name,
1742 1, 1, 0,
33f09670
JR
1743 doc: /* Return the long file name version of the full path of FILENAME.
1744If FILENAME does not exist, return nil.
1745All path elements in FILENAME are converted to their long names. */)
5842a27b 1746 (Lisp_Object filename)
b2fc9f3d
GV
1747{
1748 char longname[ MAX_PATH ];
8dcaeba2 1749 int drive_only = 0;
b2fc9f3d 1750
b7826503 1751 CHECK_STRING (filename);
b2fc9f3d 1752
8dcaeba2
JR
1753 if (SBYTES (filename) == 2
1754 && *(SDATA (filename) + 1) == ':')
1755 drive_only = 1;
1756
b2fc9f3d
GV
1757 /* first expand it. */
1758 filename = Fexpand_file_name (filename, Qnil);
1759
b23077df 1760 if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
b2fc9f3d
GV
1761 return Qnil;
1762
087fc47a 1763 dostounix_filename (longname);
b2fc9f3d 1764
8dcaeba2
JR
1765 /* If we were passed only a drive, make sure that a slash is not appended
1766 for consistency with directories. Allow for drive mapping via SUBST
1767 in case expand-file-name is ever changed to expand those. */
1768 if (drive_only && longname[1] == ':' && longname[2] == '/' && !longname[3])
1769 longname[2] = '\0';
1770
b23077df 1771 return DECODE_FILE (build_string (longname));
b2fc9f3d
GV
1772}
1773
33f09670
JR
1774DEFUN ("w32-set-process-priority", Fw32_set_process_priority,
1775 Sw32_set_process_priority, 2, 2, 0,
1776 doc: /* Set the priority of PROCESS to PRIORITY.
1777If PROCESS is nil, the priority of Emacs is changed, otherwise the
1778priority of the process whose pid is PROCESS is changed.
1779PRIORITY should be one of the symbols high, normal, or low;
1780any other symbol will be interpreted as normal.
1781
1782If successful, the return value is t, otherwise nil. */)
5842a27b 1783 (Lisp_Object process, Lisp_Object priority)
b2fc9f3d
GV
1784{
1785 HANDLE proc_handle = GetCurrentProcess ();
1786 DWORD priority_class = NORMAL_PRIORITY_CLASS;
1787 Lisp_Object result = Qnil;
1788
b7826503 1789 CHECK_SYMBOL (priority);
b2fc9f3d
GV
1790
1791 if (!NILP (process))
1792 {
1793 DWORD pid;
1794 child_process *cp;
1795
b7826503 1796 CHECK_NUMBER (process);
b2fc9f3d
GV
1797
1798 /* Allow pid to be an internally generated one, or one obtained
1799 externally. This is necessary because real pids on Win95 are
1800 negative. */
1801
1802 pid = XINT (process);
1803 cp = find_child_pid (pid);
1804 if (cp != NULL)
1805 pid = cp->procinfo.dwProcessId;
1806
1807 proc_handle = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid);
1808 }
1809
1810 if (EQ (priority, Qhigh))
1811 priority_class = HIGH_PRIORITY_CLASS;
1812 else if (EQ (priority, Qlow))
1813 priority_class = IDLE_PRIORITY_CLASS;
1814
1815 if (proc_handle != NULL)
1816 {
1817 if (SetPriorityClass (proc_handle, priority_class))
1818 result = Qt;
1819 if (!NILP (process))
1820 CloseHandle (proc_handle);
1821 }
1822
1823 return result;
1824}
1825
d613418b
EZ
1826#ifdef HAVE_LANGINFO_CODESET
1827/* Emulation of nl_langinfo. Used in fns.c:Flocale_info. */
b56ceb92
JB
1828char *
1829nl_langinfo (nl_item item)
d613418b
EZ
1830{
1831 /* Conversion of Posix item numbers to their Windows equivalents. */
1832 static const LCTYPE w32item[] = {
1833 LOCALE_IDEFAULTANSICODEPAGE,
1834 LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3,
1835 LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7,
1836 LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3,
1837 LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6,
1838 LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9,
1839 LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12
1840 };
1841
1842 static char *nl_langinfo_buf = NULL;
1843 static int nl_langinfo_len = 0;
1844
1845 if (nl_langinfo_len <= 0)
1846 nl_langinfo_buf = xmalloc (nl_langinfo_len = 1);
1847
1848 if (item < 0 || item >= _NL_NUM)
1849 nl_langinfo_buf[0] = 0;
1850 else
1851 {
1852 LCID cloc = GetThreadLocale ();
1853 int need_len = GetLocaleInfo (cloc, w32item[item] | LOCALE_USE_CP_ACP,
1854 NULL, 0);
1855
1856 if (need_len <= 0)
1857 nl_langinfo_buf[0] = 0;
1858 else
1859 {
1860 if (item == CODESET)
1861 {
1862 need_len += 2; /* for the "cp" prefix */
1863 if (need_len < 8) /* for the case we call GetACP */
1864 need_len = 8;
1865 }
1866 if (nl_langinfo_len <= need_len)
1867 nl_langinfo_buf = xrealloc (nl_langinfo_buf,
1868 nl_langinfo_len = need_len);
1869 if (!GetLocaleInfo (cloc, w32item[item] | LOCALE_USE_CP_ACP,
1870 nl_langinfo_buf, nl_langinfo_len))
1871 nl_langinfo_buf[0] = 0;
1872 else if (item == CODESET)
1873 {
1874 if (strcmp (nl_langinfo_buf, "0") == 0 /* CP_ACP */
1875 || strcmp (nl_langinfo_buf, "1") == 0) /* CP_OEMCP */
1876 sprintf (nl_langinfo_buf, "cp%u", GetACP ());
1877 else
1878 {
1879 memmove (nl_langinfo_buf + 2, nl_langinfo_buf,
1880 strlen (nl_langinfo_buf) + 1);
1881 nl_langinfo_buf[0] = 'c';
1882 nl_langinfo_buf[1] = 'p';
1883 }
1884 }
1885 }
1886 }
1887 return nl_langinfo_buf;
1888}
1889#endif /* HAVE_LANGINFO_CODESET */
b2fc9f3d 1890
33f09670
JR
1891DEFUN ("w32-get-locale-info", Fw32_get_locale_info,
1892 Sw32_get_locale_info, 1, 2, 0,
1893 doc: /* Return information about the Windows locale LCID.
1894By default, return a three letter locale code which encodes the default
35f36d65 1895language as the first two characters, and the country or regional variant
33f09670
JR
1896as the third letter. For example, ENU refers to `English (United States)',
1897while ENC means `English (Canadian)'.
1898
1899If the optional argument LONGFORM is t, the long form of the locale
1900name is returned, e.g. `English (United States)' instead; if LONGFORM
1901is a number, it is interpreted as an LCTYPE constant and the corresponding
1902locale information is returned.
1903
1904If LCID (a 16-bit number) is not a valid locale, the result is nil. */)
5842a27b 1905 (Lisp_Object lcid, Lisp_Object longform)
b2fc9f3d
GV
1906{
1907 int got_abbrev;
1908 int got_full;
1909 char abbrev_name[32] = { 0 };
1910 char full_name[256] = { 0 };
1911
b7826503 1912 CHECK_NUMBER (lcid);
b2fc9f3d
GV
1913
1914 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
1915 return Qnil;
1916
1917 if (NILP (longform))
1918 {
1919 got_abbrev = GetLocaleInfo (XINT (lcid),
1920 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1921 abbrev_name, sizeof (abbrev_name));
1922 if (got_abbrev)
1923 return build_string (abbrev_name);
1924 }
0eaf5926 1925 else if (EQ (longform, Qt))
b2fc9f3d
GV
1926 {
1927 got_full = GetLocaleInfo (XINT (lcid),
1928 LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP,
1929 full_name, sizeof (full_name));
1930 if (got_full)
011a0143 1931 return DECODE_SYSTEM (build_string (full_name));
b2fc9f3d 1932 }
0eaf5926
GV
1933 else if (NUMBERP (longform))
1934 {
1935 got_full = GetLocaleInfo (XINT (lcid),
1936 XINT (longform),
1937 full_name, sizeof (full_name));
1938 if (got_full)
1939 return make_unibyte_string (full_name, got_full);
1940 }
b2fc9f3d
GV
1941
1942 return Qnil;
1943}
1944
1945
33f09670
JR
1946DEFUN ("w32-get-current-locale-id", Fw32_get_current_locale_id,
1947 Sw32_get_current_locale_id, 0, 0, 0,
1948 doc: /* Return Windows locale id for current locale setting.
1949This is a numerical value; use `w32-get-locale-info' to convert to a
1950human-readable form. */)
5842a27b 1951 (void)
b2fc9f3d
GV
1952{
1953 return make_number (GetThreadLocale ());
1954}
1955
24f981c9 1956static DWORD
b56ceb92 1957int_from_hex (char * s)
ef79fbba
GV
1958{
1959 DWORD val = 0;
1960 static char hex[] = "0123456789abcdefABCDEF";
1961 char * p;
1962
ed3751c8 1963 while (*s && (p = strchr (hex, *s)) != NULL)
ef79fbba
GV
1964 {
1965 unsigned digit = p - hex;
1966 if (digit > 15)
1967 digit -= 6;
1968 val = val * 16 + digit;
1969 s++;
1970 }
1971 return val;
1972}
1973
1974/* We need to build a global list, since the EnumSystemLocale callback
1975 function isn't given a context pointer. */
1976Lisp_Object Vw32_valid_locale_ids;
1977
24f981c9 1978static BOOL CALLBACK
b56ceb92 1979enum_locale_fn (LPTSTR localeNum)
ef79fbba
GV
1980{
1981 DWORD id = int_from_hex (localeNum);
1982 Vw32_valid_locale_ids = Fcons (make_number (id), Vw32_valid_locale_ids);
1983 return TRUE;
1984}
1985
33f09670
JR
1986DEFUN ("w32-get-valid-locale-ids", Fw32_get_valid_locale_ids,
1987 Sw32_get_valid_locale_ids, 0, 0, 0,
1988 doc: /* Return list of all valid Windows locale ids.
1989Each id is a numerical value; use `w32-get-locale-info' to convert to a
1990human-readable form. */)
5842a27b 1991 (void)
ef79fbba
GV
1992{
1993 Vw32_valid_locale_ids = Qnil;
1994
1995 EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED);
1996
1997 Vw32_valid_locale_ids = Fnreverse (Vw32_valid_locale_ids);
1998 return Vw32_valid_locale_ids;
1999}
2000
b2fc9f3d
GV
2001
2002DEFUN ("w32-get-default-locale-id", Fw32_get_default_locale_id, Sw32_get_default_locale_id, 0, 1, 0,
33f09670
JR
2003 doc: /* Return Windows locale id for default locale setting.
2004By default, the system default locale setting is returned; if the optional
2005parameter USERP is non-nil, the user default locale setting is returned.
2006This is a numerical value; use `w32-get-locale-info' to convert to a
2007human-readable form. */)
5842a27b 2008 (Lisp_Object userp)
b2fc9f3d
GV
2009{
2010 if (NILP (userp))
2011 return make_number (GetSystemDefaultLCID ());
2012 return make_number (GetUserDefaultLCID ());
2013}
2014
177c0ea7 2015
b2fc9f3d 2016DEFUN ("w32-set-current-locale", Fw32_set_current_locale, Sw32_set_current_locale, 1, 1, 0,
33f09670
JR
2017 doc: /* Make Windows locale LCID be the current locale setting for Emacs.
2018If successful, the new locale id is returned, otherwise nil. */)
5842a27b 2019 (Lisp_Object lcid)
b2fc9f3d 2020{
b7826503 2021 CHECK_NUMBER (lcid);
b2fc9f3d
GV
2022
2023 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED))
2024 return Qnil;
2025
2026 if (!SetThreadLocale (XINT (lcid)))
2027 return Qnil;
2028
ef79fbba
GV
2029 /* Need to set input thread locale if present. */
2030 if (dwWindowsThreadId)
2031 /* Reply is not needed. */
2032 PostThreadMessage (dwWindowsThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0);
2033
b2fc9f3d
GV
2034 return make_number (GetThreadLocale ());
2035}
2036
0eaf5926
GV
2037
2038/* We need to build a global list, since the EnumCodePages callback
2039 function isn't given a context pointer. */
2040Lisp_Object Vw32_valid_codepages;
2041
24f981c9 2042static BOOL CALLBACK
b56ceb92 2043enum_codepage_fn (LPTSTR codepageNum)
0eaf5926
GV
2044{
2045 DWORD id = atoi (codepageNum);
2046 Vw32_valid_codepages = Fcons (make_number (id), Vw32_valid_codepages);
2047 return TRUE;
2048}
2049
33f09670
JR
2050DEFUN ("w32-get-valid-codepages", Fw32_get_valid_codepages,
2051 Sw32_get_valid_codepages, 0, 0, 0,
2052 doc: /* Return list of all valid Windows codepages. */)
5842a27b 2053 (void)
0eaf5926
GV
2054{
2055 Vw32_valid_codepages = Qnil;
2056
2057 EnumSystemCodePages (enum_codepage_fn, CP_SUPPORTED);
2058
2059 Vw32_valid_codepages = Fnreverse (Vw32_valid_codepages);
2060 return Vw32_valid_codepages;
2061}
2062
2063
33f09670
JR
2064DEFUN ("w32-get-console-codepage", Fw32_get_console_codepage,
2065 Sw32_get_console_codepage, 0, 0, 0,
2066 doc: /* Return current Windows codepage for console input. */)
5842a27b 2067 (void)
0eaf5926
GV
2068{
2069 return make_number (GetConsoleCP ());
2070}
2071
177c0ea7 2072
33f09670
JR
2073DEFUN ("w32-set-console-codepage", Fw32_set_console_codepage,
2074 Sw32_set_console_codepage, 1, 1, 0,
2075 doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
2076The codepage setting affects keyboard input and display in tty mode.
2077If successful, the new CP is returned, otherwise nil. */)
5842a27b 2078 (Lisp_Object cp)
0eaf5926 2079{
b7826503 2080 CHECK_NUMBER (cp);
0eaf5926
GV
2081
2082 if (!IsValidCodePage (XINT (cp)))
2083 return Qnil;
2084
2085 if (!SetConsoleCP (XINT (cp)))
2086 return Qnil;
2087
2088 return make_number (GetConsoleCP ());
2089}
2090
2091
33f09670
JR
2092DEFUN ("w32-get-console-output-codepage", Fw32_get_console_output_codepage,
2093 Sw32_get_console_output_codepage, 0, 0, 0,
2094 doc: /* Return current Windows codepage for console output. */)
5842a27b 2095 (void)
0eaf5926
GV
2096{
2097 return make_number (GetConsoleOutputCP ());
2098}
2099
177c0ea7 2100
33f09670
JR
2101DEFUN ("w32-set-console-output-codepage", Fw32_set_console_output_codepage,
2102 Sw32_set_console_output_codepage, 1, 1, 0,
2103 doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
2104The codepage setting affects keyboard input and display in tty mode.
2105If successful, the new CP is returned, otherwise nil. */)
5842a27b 2106 (Lisp_Object cp)
0eaf5926 2107{
b7826503 2108 CHECK_NUMBER (cp);
0eaf5926
GV
2109
2110 if (!IsValidCodePage (XINT (cp)))
2111 return Qnil;
2112
2113 if (!SetConsoleOutputCP (XINT (cp)))
2114 return Qnil;
2115
2116 return make_number (GetConsoleOutputCP ());
2117}
2118
2119
33f09670
JR
2120DEFUN ("w32-get-codepage-charset", Fw32_get_codepage_charset,
2121 Sw32_get_codepage_charset, 1, 1, 0,
2122 doc: /* Return charset of codepage CP.
2123Returns nil if the codepage is not valid. */)
5842a27b 2124 (Lisp_Object cp)
0eaf5926
GV
2125{
2126 CHARSETINFO info;
2127
b7826503 2128 CHECK_NUMBER (cp);
0eaf5926
GV
2129
2130 if (!IsValidCodePage (XINT (cp)))
2131 return Qnil;
2132
2133 if (TranslateCharsetInfo ((DWORD *) XINT (cp), &info, TCI_SRCCODEPAGE))
2134 return make_number (info.ciCharset);
2135
2136 return Qnil;
2137}
2138
2139
33f09670
JR
2140DEFUN ("w32-get-valid-keyboard-layouts", Fw32_get_valid_keyboard_layouts,
2141 Sw32_get_valid_keyboard_layouts, 0, 0, 0,
2142 doc: /* Return list of Windows keyboard languages and layouts.
2143The return value is a list of pairs of language id and layout id. */)
5842a27b 2144 (void)
0eaf5926
GV
2145{
2146 int num_layouts = GetKeyboardLayoutList (0, NULL);
2147 HKL * layouts = (HKL *) alloca (num_layouts * sizeof (HKL));
2148 Lisp_Object obj = Qnil;
2149
2150 if (GetKeyboardLayoutList (num_layouts, layouts) == num_layouts)
2151 {
2152 while (--num_layouts >= 0)
2153 {
2154 DWORD kl = (DWORD) layouts[num_layouts];
2155
2156 obj = Fcons (Fcons (make_number (kl & 0xffff),
2157 make_number ((kl >> 16) & 0xffff)),
2158 obj);
2159 }
2160 }
2161
2162 return obj;
2163}
2164
2165
33f09670
JR
2166DEFUN ("w32-get-keyboard-layout", Fw32_get_keyboard_layout,
2167 Sw32_get_keyboard_layout, 0, 0, 0,
2168 doc: /* Return current Windows keyboard language and layout.
2169The return value is the cons of the language id and the layout id. */)
5842a27b 2170 (void)
0eaf5926
GV
2171{
2172 DWORD kl = (DWORD) GetKeyboardLayout (dwWindowsThreadId);
2173
2174 return Fcons (make_number (kl & 0xffff),
2175 make_number ((kl >> 16) & 0xffff));
2176}
2177
177c0ea7 2178
33f09670
JR
2179DEFUN ("w32-set-keyboard-layout", Fw32_set_keyboard_layout,
2180 Sw32_set_keyboard_layout, 1, 1, 0,
2181 doc: /* Make LAYOUT be the current keyboard layout for Emacs.
2182The keyboard layout setting affects interpretation of keyboard input.
2183If successful, the new layout id is returned, otherwise nil. */)
5842a27b 2184 (Lisp_Object layout)
0eaf5926
GV
2185{
2186 DWORD kl;
2187
b7826503 2188 CHECK_CONS (layout);
f4532092
AI
2189 CHECK_NUMBER_CAR (layout);
2190 CHECK_NUMBER_CDR (layout);
0eaf5926 2191
8e713be6
KR
2192 kl = (XINT (XCAR (layout)) & 0xffff)
2193 | (XINT (XCDR (layout)) << 16);
0eaf5926
GV
2194
2195 /* Synchronize layout with input thread. */
2196 if (dwWindowsThreadId)
2197 {
2198 if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_SETKEYBOARDLAYOUT,
2199 (WPARAM) kl, 0))
2200 {
2201 MSG msg;
2202 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
2203
2204 if (msg.wParam == 0)
2205 return Qnil;
2206 }
2207 }
2208 else if (!ActivateKeyboardLayout ((HKL) kl, 0))
2209 return Qnil;
2210
2211 return Fw32_get_keyboard_layout ();
2212}
2213
b2fc9f3d 2214\f
b56ceb92
JB
2215void
2216syms_of_ntproc (void)
93fdf2f8 2217{
51128692
JR
2218 DEFSYM (Qhigh, "high");
2219 DEFSYM (Qlow, "low");
b2fc9f3d 2220
fbd6baed
GV
2221 defsubr (&Sw32_has_winsock);
2222 defsubr (&Sw32_unload_winsock);
7d701334 2223
b2fc9f3d
GV
2224 defsubr (&Sw32_short_file_name);
2225 defsubr (&Sw32_long_file_name);
2226 defsubr (&Sw32_set_process_priority);
2227 defsubr (&Sw32_get_locale_info);
2228 defsubr (&Sw32_get_current_locale_id);
2229 defsubr (&Sw32_get_default_locale_id);
ef79fbba 2230 defsubr (&Sw32_get_valid_locale_ids);
b2fc9f3d 2231 defsubr (&Sw32_set_current_locale);
a11e68d0 2232
0eaf5926
GV
2233 defsubr (&Sw32_get_console_codepage);
2234 defsubr (&Sw32_set_console_codepage);
2235 defsubr (&Sw32_get_console_output_codepage);
2236 defsubr (&Sw32_set_console_output_codepage);
2237 defsubr (&Sw32_get_valid_codepages);
2238 defsubr (&Sw32_get_codepage_charset);
2239
2240 defsubr (&Sw32_get_valid_keyboard_layouts);
2241 defsubr (&Sw32_get_keyboard_layout);
2242 defsubr (&Sw32_set_keyboard_layout);
2243
29208e82 2244 DEFVAR_LISP ("w32-quote-process-args", Vw32_quote_process_args,
33f09670
JR
2245 doc: /* Non-nil enables quoting of process arguments to ensure correct parsing.
2246Because Windows does not directly pass argv arrays to child processes,
2247programs have to reconstruct the argv array by parsing the command
2248line string. For an argument to contain a space, it must be enclosed
2249in double quotes or it will be parsed as multiple arguments.
2250
2251If the value is a character, that character will be used to escape any
2252quote characters that appear, otherwise a suitable escape character
2253will be chosen based on the type of the program. */);
b2fc9f3d 2254 Vw32_quote_process_args = Qt;
817abdf6 2255
fbd6baed 2256 DEFVAR_LISP ("w32-start-process-show-window",
29208e82 2257 Vw32_start_process_show_window,
33f09670
JR
2258 doc: /* When nil, new child processes hide their windows.
2259When non-nil, they show their window in the method of their choice.
2260This variable doesn't affect GUI applications, which will never be hidden. */);
fbd6baed 2261 Vw32_start_process_show_window = Qnil;
0ecf7d36 2262
b2fc9f3d 2263 DEFVAR_LISP ("w32-start-process-share-console",
29208e82 2264 Vw32_start_process_share_console,
33f09670
JR
2265 doc: /* When nil, new child processes are given a new console.
2266When non-nil, they share the Emacs console; this has the limitation of
804d894a 2267allowing only one DOS subprocess to run at a time (whether started directly
33f09670
JR
2268or indirectly by Emacs), and preventing Emacs from cleanly terminating the
2269subprocess group, but may allow Emacs to interrupt a subprocess that doesn't
2270otherwise respond to interrupts from Emacs. */);
b2fc9f3d
GV
2271 Vw32_start_process_share_console = Qnil;
2272
82e7c0a9 2273 DEFVAR_LISP ("w32-start-process-inherit-error-mode",
29208e82 2274 Vw32_start_process_inherit_error_mode,
33f09670
JR
2275 doc: /* When nil, new child processes revert to the default error mode.
2276When non-nil, they inherit their error mode setting from Emacs, which stops
2277them blocking when trying to access unmounted drives etc. */);
82e7c0a9
AI
2278 Vw32_start_process_inherit_error_mode = Qt;
2279
29208e82 2280 DEFVAR_INT ("w32-pipe-read-delay", w32_pipe_read_delay,
33f09670
JR
2281 doc: /* Forced delay before reading subprocess output.
2282This is done to improve the buffering of subprocess output, by
2283avoiding the inefficiency of frequently reading small amounts of data.
2284
2285If positive, the value is the number of milliseconds to sleep before
2286reading the subprocess output. If negative, the magnitude is the number
2287of time slices to wait (effectively boosting the priority of the child
2288process temporarily). A value of zero disables waiting entirely. */);
5322f50b 2289 w32_pipe_read_delay = 50;
0c04091e 2290
29208e82 2291 DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names,
33f09670
JR
2292 doc: /* Non-nil means convert all-upper case file names to lower case.
2293This applies when performing completions and file name expansion.
2294Note that the value of this setting also affects remote file names,
2295so you probably don't want to set to non-nil if you use case-sensitive
177c0ea7 2296filesystems via ange-ftp. */);
fbd6baed 2297 Vw32_downcase_file_names = Qnil;
b2fc9f3d
GV
2298
2299#if 0
29208e82 2300 DEFVAR_LISP ("w32-generate-fake-inodes", Vw32_generate_fake_inodes,
33f09670
JR
2301 doc: /* Non-nil means attempt to fake realistic inode values.
2302This works by hashing the truename of files, and should detect
2303aliasing between long and short (8.3 DOS) names, but can have
2304false positives because of hash collisions. Note that determing
2305the truename of a file can be slow. */);
b2fc9f3d
GV
2306 Vw32_generate_fake_inodes = Qnil;
2307#endif
2308
29208e82 2309 DEFVAR_LISP ("w32-get-true-file-attributes", Vw32_get_true_file_attributes,
ed4c17bb
EZ
2310 doc: /* Non-nil means determine accurate file attributes in `file-attributes'.
2311This option controls whether to issue additional system calls to determine
017dab84 2312accurate link counts, file type, and ownership information. It is more
ed4c17bb 2313useful for files on NTFS volumes, where hard links and file security are
017dab84 2314supported, than on volumes of the FAT family.
ed4c17bb
EZ
2315
2316Without these system calls, link count will always be reported as 1 and file
2317ownership will be attributed to the current user.
2318The default value `local' means only issue these system calls for files
2319on local fixed drives. A value of nil means never issue them.
2320Any other non-nil value means do this even on remote and removable drives
2321where the performance impact may be noticeable even on modern hardware. */);
2fa4f090 2322 Vw32_get_true_file_attributes = Qlocal;
af621bc3
EZ
2323
2324 staticpro (&Vw32_valid_locale_ids);
2325 staticpro (&Vw32_valid_codepages);
93fdf2f8 2326}
42a7e7f1 2327/* end of w32proc.c */
ab5796a9 2328