Commit | Line | Data |
---|---|---|
6cdfb6e6 | 1 | /* Process support for Windows NT port of GNU EMACS. |
22759c72 | 2 | Copyright (C) 1992, 1995 Free Software Foundation, Inc. |
6cdfb6e6 | 3 | |
3b7ad313 EN |
4 | This file is part of GNU Emacs. |
5 | ||
6 | GNU Emacs is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GNU Emacs is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Emacs; 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. | |
6cdfb6e6 RS |
20 | |
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 RS |
30 | #include <signal.h> |
31 | ||
c519b5e1 GV |
32 | /* must include CRT headers *before* config.h */ |
33 | #include "config.h" | |
34 | #undef signal | |
35 | #undef wait | |
36 | #undef spawnve | |
37 | #undef select | |
38 | #undef kill | |
39 | ||
6cdfb6e6 RS |
40 | #include <windows.h> |
41 | ||
42 | #include "lisp.h" | |
43 | #include "nt.h" | |
44 | #include "systime.h" | |
3d7eead0 GV |
45 | #include "syswait.h" |
46 | #include "process.h" | |
47 | ||
93fdf2f8 RS |
48 | /* Control whether spawnve quotes arguments as necessary to ensure |
49 | correct parsing by child process. Because not all uses of spawnve | |
50 | are careful about constructing argv arrays, we make this behaviour | |
51 | conditional (off by default). */ | |
52 | Lisp_Object Vwin32_quote_process_args; | |
53 | ||
3d7eead0 GV |
54 | #ifndef SYS_SIGLIST_DECLARED |
55 | extern char *sys_siglist[]; | |
56 | #endif | |
6cdfb6e6 | 57 | |
6cdfb6e6 | 58 | #ifdef EMACSDEBUG |
c519b5e1 | 59 | void _DebPrint (const char *fmt, ...) |
6cdfb6e6 | 60 | { |
c519b5e1 | 61 | char buf[1024]; |
6cdfb6e6 RS |
62 | va_list args; |
63 | ||
64 | va_start (args, fmt); | |
65 | vsprintf (buf, fmt, args); | |
66 | va_end (args); | |
67 | OutputDebugString (buf); | |
68 | } | |
69 | #endif | |
70 | ||
c519b5e1 | 71 | typedef void (_CALLBACK_ *signal_handler)(int); |
6cdfb6e6 RS |
72 | |
73 | /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */ | |
74 | static signal_handler sig_handlers[NSIG]; | |
75 | ||
76 | /* Fake signal implementation to record the SIGCHLD handler. */ | |
77 | signal_handler | |
c519b5e1 | 78 | sys_signal (int sig, signal_handler handler) |
6cdfb6e6 RS |
79 | { |
80 | signal_handler old; | |
81 | ||
82 | if (sig != SIGCHLD) | |
83 | { | |
84 | errno = EINVAL; | |
85 | return SIG_ERR; | |
86 | } | |
87 | old = sig_handlers[sig]; | |
88 | sig_handlers[sig] = handler; | |
89 | return old; | |
90 | } | |
91 | ||
c519b5e1 GV |
92 | /* Defined in <process.h> which conflicts with the local copy */ |
93 | #define _P_NOWAIT 1 | |
94 | ||
95 | /* Child process management list. */ | |
96 | int child_proc_count = 0; | |
97 | child_process child_procs[ MAX_CHILDREN ]; | |
98 | child_process *dead_child = NULL; | |
99 | ||
100 | DWORD WINAPI reader_thread (void *arg); | |
101 | ||
6cdfb6e6 | 102 | /* Find an unused process slot. */ |
c519b5e1 | 103 | child_process * |
6cdfb6e6 RS |
104 | new_child (void) |
105 | { | |
106 | child_process *cp; | |
c519b5e1 | 107 | DWORD id; |
6cdfb6e6 RS |
108 | |
109 | for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
110 | if (!CHILD_ACTIVE (cp)) | |
c519b5e1 GV |
111 | goto Initialise; |
112 | if (child_proc_count == MAX_CHILDREN) | |
113 | return NULL; | |
114 | cp = &child_procs[child_proc_count++]; | |
115 | ||
116 | Initialise: | |
117 | memset (cp, 0, sizeof(*cp)); | |
118 | cp->fd = -1; | |
119 | cp->pid = -1; | |
120 | cp->procinfo.hProcess = NULL; | |
121 | cp->status = STATUS_READ_ERROR; | |
122 | ||
123 | /* use manual reset event so that select() will function properly */ | |
124 | cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL); | |
125 | if (cp->char_avail) | |
126 | { | |
127 | cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL); | |
128 | if (cp->char_consumed) | |
129 | { | |
130 | cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id); | |
131 | if (cp->thrd) | |
132 | return cp; | |
133 | } | |
134 | } | |
135 | delete_child (cp); | |
136 | return NULL; | |
137 | } | |
138 | ||
139 | void | |
140 | delete_child (child_process *cp) | |
141 | { | |
142 | int i; | |
143 | ||
144 | /* Should not be deleting a child that is still needed. */ | |
145 | for (i = 0; i < MAXDESC; i++) | |
146 | if (fd_info[i].cp == cp) | |
147 | abort (); | |
148 | ||
149 | if (!CHILD_ACTIVE (cp)) | |
150 | return; | |
151 | ||
152 | /* reap thread if necessary */ | |
153 | if (cp->thrd) | |
154 | { | |
155 | DWORD rc; | |
156 | ||
157 | if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE) | |
158 | { | |
159 | /* let the thread exit cleanly if possible */ | |
160 | cp->status = STATUS_READ_ERROR; | |
161 | SetEvent (cp->char_consumed); | |
162 | if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0) | |
163 | { | |
164 | DebPrint (("delete_child.WaitForSingleObject (thread) failed " | |
165 | "with %lu for fd %ld\n", GetLastError (), cp->fd)); | |
166 | TerminateThread (cp->thrd, 0); | |
167 | } | |
168 | } | |
169 | CloseHandle (cp->thrd); | |
170 | cp->thrd = NULL; | |
171 | } | |
172 | if (cp->char_avail) | |
173 | { | |
174 | CloseHandle (cp->char_avail); | |
175 | cp->char_avail = NULL; | |
176 | } | |
177 | if (cp->char_consumed) | |
178 | { | |
179 | CloseHandle (cp->char_consumed); | |
180 | cp->char_consumed = NULL; | |
181 | } | |
182 | ||
183 | /* update child_proc_count (highest numbered slot in use plus one) */ | |
184 | if (cp == child_procs + child_proc_count - 1) | |
185 | { | |
186 | for (i = child_proc_count-1; i >= 0; i--) | |
187 | if (CHILD_ACTIVE (&child_procs[i])) | |
188 | { | |
189 | child_proc_count = i + 1; | |
190 | break; | |
191 | } | |
192 | } | |
193 | if (i < 0) | |
194 | child_proc_count = 0; | |
6cdfb6e6 RS |
195 | } |
196 | ||
197 | /* Find a child by pid. */ | |
198 | static child_process * | |
199 | find_child_pid (DWORD pid) | |
200 | { | |
201 | child_process *cp; | |
c519b5e1 | 202 | |
6cdfb6e6 RS |
203 | for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) |
204 | if (CHILD_ACTIVE (cp) && pid == cp->pid) | |
205 | return cp; | |
206 | return NULL; | |
207 | } | |
208 | ||
6cdfb6e6 | 209 | |
c519b5e1 GV |
210 | /* Thread proc for child process and socket reader threads. Each thread |
211 | is normally blocked until woken by select() to check for input by | |
212 | reading one char. When the read completes, char_avail is signalled | |
213 | to wake up the select emulator and the thread blocks itself again. */ | |
6cdfb6e6 RS |
214 | DWORD WINAPI |
215 | reader_thread (void *arg) | |
216 | { | |
217 | child_process *cp; | |
218 | ||
219 | /* Our identity */ | |
220 | cp = (child_process *)arg; | |
221 | ||
222 | /* We have to wait for the go-ahead before we can start */ | |
c519b5e1 GV |
223 | if (cp == NULL || |
224 | WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) | |
225 | return 1; | |
226 | ||
6cdfb6e6 RS |
227 | for (;;) |
228 | { | |
c519b5e1 GV |
229 | int rc; |
230 | ||
231 | rc = _sys_read_ahead (cp->fd); | |
232 | ||
233 | /* The name char_avail is a misnomer - it really just means the | |
234 | read-ahead has completed, whether successfully or not. */ | |
6cdfb6e6 RS |
235 | if (!SetEvent (cp->char_avail)) |
236 | { | |
237 | DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n", | |
238 | GetLastError (), cp->fd)); | |
c519b5e1 GV |
239 | return 1; |
240 | } | |
241 | ||
242 | if (rc == STATUS_READ_ERROR) | |
243 | return 1; | |
6cdfb6e6 RS |
244 | |
245 | /* If the read died, the child has died so let the thread die */ | |
c519b5e1 | 246 | if (rc == STATUS_READ_FAILED) |
6cdfb6e6 RS |
247 | break; |
248 | ||
249 | /* Wait until our input is acknowledged before reading again */ | |
250 | if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0) | |
251 | { | |
252 | DebPrint (("reader_thread.WaitForSingleObject failed with " | |
253 | "%lu for fd %ld\n", GetLastError (), cp->fd)); | |
254 | break; | |
255 | } | |
256 | } | |
257 | return 0; | |
258 | } | |
259 | ||
260 | static BOOL | |
261 | create_child (char *exe, char *cmdline, char *env, | |
c519b5e1 | 262 | int * pPid, child_process *cp) |
6cdfb6e6 | 263 | { |
6cdfb6e6 RS |
264 | STARTUPINFO start; |
265 | SECURITY_ATTRIBUTES sec_attrs; | |
266 | SECURITY_DESCRIPTOR sec_desc; | |
267 | ||
c519b5e1 | 268 | if (cp == NULL) abort (); |
6cdfb6e6 RS |
269 | |
270 | memset (&start, 0, sizeof (start)); | |
271 | start.cb = sizeof (start); | |
272 | ||
58d4e829 GV |
273 | #ifdef HAVE_NTGUI |
274 | start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
275 | start.wShowWindow = SW_HIDE; | |
276 | ||
277 | start.hStdInput = GetStdHandle (STD_INPUT_HANDLE); | |
278 | start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); | |
279 | start.hStdError = GetStdHandle (STD_ERROR_HANDLE); | |
280 | #endif /* HAVE_NTGUI */ | |
281 | ||
6cdfb6e6 RS |
282 | /* Explicitly specify no security */ |
283 | if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION)) | |
c519b5e1 | 284 | goto EH_Fail; |
6cdfb6e6 | 285 | if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE)) |
c519b5e1 | 286 | goto EH_Fail; |
6cdfb6e6 RS |
287 | sec_attrs.nLength = sizeof (sec_attrs); |
288 | sec_attrs.lpSecurityDescriptor = &sec_desc; | |
289 | sec_attrs.bInheritHandle = FALSE; | |
290 | ||
291 | if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, | |
c519b5e1 GV |
292 | CREATE_NEW_PROCESS_GROUP, |
293 | env, NULL, | |
294 | &start, &cp->procinfo)) | |
295 | goto EH_Fail; | |
296 | ||
297 | cp->pid = (int) cp->procinfo.dwProcessId; | |
298 | ||
299 | /* Hack for Windows 95, which assigns large (ie negative) pids */ | |
300 | if (cp->pid < 0) | |
301 | cp->pid = -cp->pid; | |
302 | ||
303 | /* pid must fit in a Lisp_Int */ | |
304 | cp->pid = (cp->pid & VALMASK); | |
305 | ||
306 | ||
307 | *pPid = cp->pid; | |
6cdfb6e6 RS |
308 | |
309 | return TRUE; | |
310 | ||
6cdfb6e6 | 311 | EH_Fail: |
c519b5e1 | 312 | DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError());); |
6cdfb6e6 RS |
313 | return FALSE; |
314 | } | |
315 | ||
316 | /* create_child doesn't know what emacs' file handle will be for waiting | |
317 | on output from the child, so we need to make this additional call | |
318 | to register the handle with the process | |
319 | This way the select emulator knows how to match file handles with | |
320 | entries in child_procs. */ | |
321 | void | |
322 | register_child (int pid, int fd) | |
323 | { | |
324 | child_process *cp; | |
325 | ||
326 | cp = find_child_pid (pid); | |
327 | if (cp == NULL) | |
328 | { | |
329 | DebPrint (("register_child unable to find pid %lu\n", pid)); | |
330 | return; | |
331 | } | |
332 | ||
333 | #ifdef FULL_DEBUG | |
334 | DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid)); | |
335 | #endif | |
336 | ||
337 | cp->fd = fd; | |
6cdfb6e6 | 338 | |
c519b5e1 GV |
339 | /* thread is initially blocked until select is called; set status so |
340 | that select will release thread */ | |
341 | cp->status = STATUS_READ_ACKNOWLEDGED; | |
342 | ||
343 | /* attach child_process to fd_info */ | |
344 | if (fd_info[fd].cp != NULL) | |
6cdfb6e6 | 345 | { |
c519b5e1 GV |
346 | DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd)); |
347 | abort (); | |
6cdfb6e6 | 348 | } |
c519b5e1 GV |
349 | |
350 | fd_info[fd].cp = cp; | |
6cdfb6e6 RS |
351 | } |
352 | ||
353 | /* When a process dies its pipe will break so the reader thread will | |
354 | signal failure to the select emulator. | |
355 | The select emulator then calls this routine to clean up. | |
356 | Since the thread signaled failure we can assume it is exiting. */ | |
357 | static void | |
c519b5e1 | 358 | reap_subprocess (child_process *cp) |
6cdfb6e6 | 359 | { |
c519b5e1 | 360 | if (cp->procinfo.hProcess) |
6cdfb6e6 | 361 | { |
c519b5e1 GV |
362 | /* Reap the process */ |
363 | if (WaitForSingleObject (cp->procinfo.hProcess, INFINITE) != WAIT_OBJECT_0) | |
364 | DebPrint (("reap_subprocess.WaitForSingleObject (process) failed " | |
365 | "with %lu for fd %ld\n", GetLastError (), cp->fd)); | |
366 | CloseHandle (cp->procinfo.hProcess); | |
367 | cp->procinfo.hProcess = NULL; | |
368 | CloseHandle (cp->procinfo.hThread); | |
369 | cp->procinfo.hThread = NULL; | |
6cdfb6e6 | 370 | } |
c519b5e1 GV |
371 | |
372 | /* For asynchronous children, the child_proc resources will be freed | |
373 | when the last pipe read descriptor is closed; for synchronous | |
374 | children, we must explicitly free the resources now because | |
375 | register_child has not been called. */ | |
376 | if (cp->fd == -1) | |
377 | delete_child (cp); | |
6cdfb6e6 RS |
378 | } |
379 | ||
380 | /* Wait for any of our existing child processes to die | |
381 | When it does, close its handle | |
382 | Return the pid and fill in the status if non-NULL. */ | |
22759c72 | 383 | |
6cdfb6e6 | 384 | int |
c519b5e1 | 385 | sys_wait (int *status) |
6cdfb6e6 RS |
386 | { |
387 | DWORD active, retval; | |
388 | int nh; | |
c519b5e1 | 389 | int pid; |
6cdfb6e6 RS |
390 | child_process *cp, *cps[MAX_CHILDREN]; |
391 | HANDLE wait_hnd[MAX_CHILDREN]; | |
392 | ||
393 | nh = 0; | |
394 | if (dead_child != NULL) | |
395 | { | |
396 | /* We want to wait for a specific child */ | |
c519b5e1 | 397 | wait_hnd[nh] = dead_child->procinfo.hProcess; |
6cdfb6e6 | 398 | cps[nh] = dead_child; |
c519b5e1 | 399 | if (!wait_hnd[nh]) abort (); |
6cdfb6e6 RS |
400 | nh++; |
401 | } | |
402 | else | |
403 | { | |
404 | for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) | |
c519b5e1 GV |
405 | /* some child_procs might be sockets; ignore them */ |
406 | if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess) | |
6cdfb6e6 | 407 | { |
c519b5e1 | 408 | wait_hnd[nh] = cp->procinfo.hProcess; |
6cdfb6e6 | 409 | cps[nh] = cp; |
c519b5e1 | 410 | if (!wait_hnd[nh]) abort (); |
6cdfb6e6 RS |
411 | nh++; |
412 | } | |
413 | } | |
414 | ||
415 | if (nh == 0) | |
416 | { | |
417 | /* Nothing to wait on, so fail */ | |
418 | errno = ECHILD; | |
419 | return -1; | |
420 | } | |
421 | ||
422 | active = WaitForMultipleObjects (nh, wait_hnd, FALSE, INFINITE); | |
423 | if (active == WAIT_FAILED) | |
424 | { | |
425 | errno = EBADF; | |
426 | return -1; | |
427 | } | |
428 | else if (active == WAIT_TIMEOUT) | |
429 | { | |
430 | /* Should never happen */ | |
431 | errno = EINVAL; | |
432 | return -1; | |
433 | } | |
434 | else if (active >= WAIT_OBJECT_0 && | |
435 | active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) | |
436 | { | |
437 | active -= WAIT_OBJECT_0; | |
438 | } | |
439 | else if (active >= WAIT_ABANDONED_0 && | |
440 | active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | |
441 | { | |
442 | active -= WAIT_ABANDONED_0; | |
443 | } | |
444 | ||
445 | if (!GetExitCodeProcess (wait_hnd[active], &retval)) | |
446 | { | |
447 | DebPrint (("Wait.GetExitCodeProcess failed with %lu\n", | |
448 | GetLastError ())); | |
449 | retval = 1; | |
450 | } | |
451 | if (retval == STILL_ACTIVE) | |
452 | { | |
453 | /* Should never happen */ | |
454 | DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); | |
455 | errno = EINVAL; | |
456 | return -1; | |
457 | } | |
bc69349b RS |
458 | |
459 | /* Massage the exit code from the process to match the format expected | |
8e6208c5 | 460 | by the WIFSTOPPED et al macros in syswait.h. Only WIFSIGNALED and |
bc69349b RS |
461 | WIFEXITED are supported; WIFSTOPPED doesn't make sense under NT. */ |
462 | ||
463 | if (retval == STATUS_CONTROL_C_EXIT) | |
464 | retval = SIGINT; | |
465 | else | |
466 | retval <<= 8; | |
c519b5e1 | 467 | |
6cdfb6e6 | 468 | cp = cps[active]; |
c519b5e1 GV |
469 | pid = cp->pid; |
470 | #ifdef FULL_DEBUG | |
471 | DebPrint (("Wait signaled with process pid %d\n", cp->pid)); | |
472 | #endif | |
22759c72 | 473 | |
6cdfb6e6 RS |
474 | if (status) |
475 | { | |
22759c72 KH |
476 | *status = retval; |
477 | } | |
478 | else if (synch_process_alive) | |
479 | { | |
480 | synch_process_alive = 0; | |
22759c72 | 481 | |
3d7eead0 GV |
482 | /* Report the status of the synchronous process. */ |
483 | if (WIFEXITED (retval)) | |
484 | synch_process_retcode = WRETCODE (retval); | |
485 | else if (WIFSIGNALED (retval)) | |
486 | { | |
487 | int code = WTERMSIG (retval); | |
488 | char *signame = 0; | |
489 | ||
490 | if (code < NSIG) | |
491 | { | |
492 | /* Suppress warning if the table has const char *. */ | |
493 | signame = (char *) sys_siglist[code]; | |
494 | } | |
495 | if (signame == 0) | |
496 | signame = "unknown"; | |
497 | ||
498 | synch_process_death = signame; | |
499 | } | |
c519b5e1 GV |
500 | |
501 | reap_subprocess (cp); | |
6cdfb6e6 RS |
502 | } |
503 | ||
c519b5e1 | 504 | return pid; |
6cdfb6e6 RS |
505 | } |
506 | ||
507 | /* We pass our process ID to our children by setting up an environment | |
508 | variable in their environment. */ | |
509 | char ppid_env_var_buffer[64]; | |
510 | ||
511 | /* When a new child process is created we need to register it in our list, | |
512 | so intercept spawn requests. */ | |
513 | int | |
c519b5e1 | 514 | sys_spawnve (int mode, char *cmdname, char **argv, char **envp) |
6cdfb6e6 | 515 | { |
0a4de642 | 516 | Lisp_Object program, full; |
6cdfb6e6 RS |
517 | char *cmdline, *env, *parg, **targ; |
518 | int arglen; | |
c519b5e1 GV |
519 | int pid; |
520 | child_process *cp; | |
521 | ||
522 | /* We don't care about the other modes */ | |
523 | if (mode != _P_NOWAIT) | |
524 | { | |
525 | errno = EINVAL; | |
526 | return -1; | |
527 | } | |
0a4de642 RS |
528 | |
529 | /* Handle executable names without an executable suffix. */ | |
530 | program = make_string (cmdname, strlen (cmdname)); | |
531 | if (NILP (Ffile_executable_p (program))) | |
532 | { | |
533 | struct gcpro gcpro1; | |
534 | ||
535 | full = Qnil; | |
536 | GCPRO1 (program); | |
537 | openp (Vexec_path, program, EXEC_SUFFIXES, &full, 1); | |
538 | UNGCPRO; | |
539 | if (NILP (full)) | |
540 | { | |
541 | errno = EINVAL; | |
542 | return -1; | |
543 | } | |
544 | cmdname = XSTRING (full)->data; | |
545 | argv[0] = cmdname; | |
546 | } | |
547 | ||
c519b5e1 GV |
548 | /* make sure cmdname is in DOS format */ |
549 | strcpy (cmdname = alloca (strlen (cmdname) + 1), argv[0]); | |
550 | unixtodos_filename (cmdname); | |
551 | argv[0] = cmdname; | |
6cdfb6e6 RS |
552 | |
553 | /* we have to do some conjuring here to put argv and envp into the | |
554 | form CreateProcess wants... argv needs to be a space separated/null | |
555 | terminated list of parameters, and envp is a null | |
556 | separated/double-null terminated list of parameters. | |
c519b5e1 GV |
557 | |
558 | Additionally, zero-length args and args containing whitespace need | |
559 | to be wrapped in double quotes. Args containing embedded double | |
560 | quotes (as opposed to enclosing quotes, which we leave alone) are | |
561 | usually illegal (most Win32 programs do not implement escaping of | |
562 | double quotes - sad but true, at least for programs compiled with | |
563 | MSVC), but we will escape quotes anyway for those programs that can | |
564 | handle it. The Win32 gcc library from Cygnus doubles quotes to | |
565 | escape them, so we will use that convention. | |
6cdfb6e6 RS |
566 | |
567 | Since I have no idea how large argv and envp are likely to be | |
568 | we figure out list lengths on the fly and allocate them. */ | |
569 | ||
570 | /* do argv... */ | |
571 | arglen = 0; | |
572 | targ = argv; | |
573 | while (*targ) | |
574 | { | |
c519b5e1 GV |
575 | char * p = *targ; |
576 | int add_quotes = 0; | |
577 | ||
578 | if (*p == 0) | |
579 | add_quotes = 1; | |
580 | while (*p) | |
581 | if (*p++ == '"') | |
582 | { | |
583 | /* allow for embedded quotes to be doubled - we won't | |
584 | actually double quotes that aren't embedded though */ | |
585 | arglen++; | |
586 | add_quotes = 1; | |
587 | } | |
588 | else if (*p == ' ' || *p == '\t') | |
589 | add_quotes = 1; | |
590 | if (add_quotes) | |
591 | arglen += 2; | |
6cdfb6e6 RS |
592 | arglen += strlen (*targ++) + 1; |
593 | } | |
c519b5e1 | 594 | cmdline = alloca (arglen); |
6cdfb6e6 RS |
595 | targ = argv; |
596 | parg = cmdline; | |
597 | while (*targ) | |
598 | { | |
c519b5e1 GV |
599 | char * p = *targ; |
600 | int add_quotes = 0; | |
601 | ||
602 | if (*p == 0) | |
603 | add_quotes = 1; | |
93fdf2f8 RS |
604 | |
605 | if (!NILP (Vwin32_quote_process_args)) | |
606 | { | |
607 | /* This is conditional because it sometimes causes more | |
608 | problems than it solves, since argv arrays are not always | |
609 | carefully constructed. M-x grep, for instance, passes the | |
610 | whole command line as one argument, so it becomes | |
611 | impossible to pass a regexp which contains spaces. */ | |
612 | for ( ; *p; p++) | |
613 | if (*p == ' ' || *p == '\t' || *p == '"') | |
614 | add_quotes = 1; | |
615 | } | |
c519b5e1 GV |
616 | if (add_quotes) |
617 | { | |
618 | char * first; | |
619 | char * last; | |
620 | ||
621 | p = *targ; | |
622 | first = p; | |
623 | last = p + strlen (p) - 1; | |
624 | *parg++ = '"'; | |
625 | while (*p) | |
626 | { | |
627 | if (*p == '"' && p > first && p < last) | |
628 | *parg++ = '"'; /* double up embedded quotes only */ | |
629 | *parg++ = *p++; | |
630 | } | |
631 | *parg++ = '"'; | |
632 | } | |
633 | else | |
634 | { | |
635 | strcpy (parg, *targ); | |
636 | parg += strlen (*targ); | |
637 | } | |
6cdfb6e6 | 638 | *parg++ = ' '; |
c519b5e1 | 639 | targ++; |
6cdfb6e6 RS |
640 | } |
641 | *--parg = '\0'; | |
642 | ||
643 | /* and envp... */ | |
644 | arglen = 1; | |
645 | targ = envp; | |
646 | while (*targ) | |
647 | { | |
648 | arglen += strlen (*targ++) + 1; | |
649 | } | |
650 | sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d", | |
651 | GetCurrentProcessId ()); | |
652 | arglen += strlen (ppid_env_var_buffer) + 1; | |
653 | ||
c519b5e1 | 654 | env = alloca (arglen); |
6cdfb6e6 RS |
655 | targ = envp; |
656 | parg = env; | |
657 | while (*targ) | |
658 | { | |
659 | strcpy (parg, *targ); | |
660 | parg += strlen (*targ++); | |
661 | *parg++ = '\0'; | |
662 | } | |
663 | strcpy (parg, ppid_env_var_buffer); | |
664 | parg += strlen (ppid_env_var_buffer); | |
665 | *parg++ = '\0'; | |
666 | *parg = '\0'; | |
c519b5e1 GV |
667 | |
668 | cp = new_child (); | |
669 | if (cp == NULL) | |
670 | { | |
671 | errno = EAGAIN; | |
672 | return -1; | |
673 | } | |
6cdfb6e6 RS |
674 | |
675 | /* Now create the process. */ | |
c519b5e1 | 676 | if (!create_child (cmdname, cmdline, env, &pid, cp)) |
6cdfb6e6 | 677 | { |
c519b5e1 | 678 | delete_child (cp); |
6cdfb6e6 | 679 | errno = ENOEXEC; |
c519b5e1 | 680 | return -1; |
6cdfb6e6 RS |
681 | } |
682 | ||
c519b5e1 | 683 | return pid; |
6cdfb6e6 RS |
684 | } |
685 | ||
686 | /* Emulate the select call | |
687 | Wait for available input on any of the given rfds, or timeout if | |
688 | a timeout is given and no input is detected | |
689 | wfds and efds are not supported and must be NULL. */ | |
690 | ||
691 | /* From ntterm.c */ | |
692 | extern HANDLE keyboard_handle; | |
693 | /* From process.c */ | |
694 | extern int proc_buffered_char[]; | |
695 | ||
696 | int | |
22759c72 KH |
697 | sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, |
698 | EMACS_TIME *timeout) | |
6cdfb6e6 RS |
699 | { |
700 | SELECT_TYPE orfds; | |
701 | DWORD timeout_ms; | |
702 | int i, nh, nr; | |
703 | DWORD active; | |
c519b5e1 GV |
704 | child_process *cp; |
705 | HANDLE wait_hnd[MAXDESC]; | |
706 | int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ | |
6cdfb6e6 RS |
707 | |
708 | /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ | |
709 | if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) | |
710 | { | |
22759c72 | 711 | Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); |
6cdfb6e6 RS |
712 | return 0; |
713 | } | |
714 | ||
715 | /* Otherwise, we only handle rfds, so fail otherwise. */ | |
716 | if (rfds == NULL || wfds != NULL || efds != NULL) | |
717 | { | |
718 | errno = EINVAL; | |
719 | return -1; | |
720 | } | |
721 | ||
722 | orfds = *rfds; | |
723 | FD_ZERO (rfds); | |
724 | nr = 0; | |
725 | ||
726 | /* Build a list of handles to wait on. */ | |
727 | nh = 0; | |
728 | for (i = 0; i < nfds; i++) | |
729 | if (FD_ISSET (i, &orfds)) | |
730 | { | |
731 | if (i == 0) | |
732 | { | |
c519b5e1 GV |
733 | if (keyboard_handle) |
734 | { | |
735 | /* Handle stdin specially */ | |
736 | wait_hnd[nh] = keyboard_handle; | |
737 | fdindex[nh] = i; | |
738 | nh++; | |
739 | } | |
6cdfb6e6 RS |
740 | |
741 | /* Check for any emacs-generated input in the queue since | |
742 | it won't be detected in the wait */ | |
743 | if (detect_input_pending ()) | |
744 | { | |
745 | FD_SET (i, rfds); | |
c519b5e1 | 746 | return 1; |
6cdfb6e6 RS |
747 | } |
748 | } | |
749 | else | |
750 | { | |
c519b5e1 GV |
751 | /* Child process and socket input */ |
752 | cp = fd_info[i].cp; | |
6cdfb6e6 RS |
753 | if (cp) |
754 | { | |
c519b5e1 GV |
755 | int current_status = cp->status; |
756 | ||
757 | if (current_status == STATUS_READ_ACKNOWLEDGED) | |
758 | { | |
759 | /* Tell reader thread which file handle to use. */ | |
760 | cp->fd = i; | |
761 | /* Wake up the reader thread for this process */ | |
762 | cp->status = STATUS_READ_READY; | |
763 | if (!SetEvent (cp->char_consumed)) | |
764 | DebPrint (("nt_select.SetEvent failed with " | |
765 | "%lu for fd %ld\n", GetLastError (), i)); | |
766 | } | |
767 | ||
768 | #ifdef CHECK_INTERLOCK | |
769 | /* slightly crude cross-checking of interlock between threads */ | |
770 | ||
771 | current_status = cp->status; | |
772 | if (WaitForSingleObject (cp->char_avail, 0) == WAIT_OBJECT_0) | |
773 | { | |
774 | /* char_avail has been signalled, so status (which may | |
775 | have changed) should indicate read has completed | |
776 | but has not been acknowledged. */ | |
777 | current_status = cp->status; | |
778 | if (current_status != STATUS_READ_SUCCEEDED && | |
779 | current_status != STATUS_READ_FAILED) | |
780 | DebPrint (("char_avail set, but read not completed: status %d\n", | |
781 | current_status)); | |
782 | } | |
783 | else | |
784 | { | |
785 | /* char_avail has not been signalled, so status should | |
786 | indicate that read is in progress; small possibility | |
787 | that read has completed but event wasn't yet signalled | |
788 | when we tested it (because a context switch occurred | |
789 | or if running on separate CPUs). */ | |
790 | if (current_status != STATUS_READ_READY && | |
791 | current_status != STATUS_READ_IN_PROGRESS && | |
792 | current_status != STATUS_READ_SUCCEEDED && | |
793 | current_status != STATUS_READ_FAILED) | |
794 | DebPrint (("char_avail reset, but read status is bad: %d\n", | |
795 | current_status)); | |
796 | } | |
797 | #endif | |
798 | wait_hnd[nh] = cp->char_avail; | |
799 | fdindex[nh] = i; | |
800 | if (!wait_hnd[nh]) abort (); | |
801 | nh++; | |
6cdfb6e6 RS |
802 | #ifdef FULL_DEBUG |
803 | DebPrint (("select waiting on child %d fd %d\n", | |
804 | cp-child_procs, i)); | |
805 | #endif | |
6cdfb6e6 RS |
806 | } |
807 | else | |
808 | { | |
c519b5e1 GV |
809 | /* Unable to find something to wait on for this fd, skip */ |
810 | DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i)); | |
811 | abort (); | |
6cdfb6e6 RS |
812 | } |
813 | } | |
814 | } | |
815 | ||
816 | /* Nothing to look for, so we didn't find anything */ | |
817 | if (nh == 0) | |
818 | { | |
22759c72 | 819 | if (timeout) |
22759c72 | 820 | Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); |
6cdfb6e6 RS |
821 | return 0; |
822 | } | |
6cdfb6e6 RS |
823 | |
824 | /* | |
825 | Wait for input | |
826 | If a child process dies while this is waiting, its pipe will break | |
827 | so the reader thread will signal an error condition, thus, the wait | |
828 | will wake up | |
829 | */ | |
22759c72 | 830 | timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; |
c519b5e1 | 831 | |
6cdfb6e6 | 832 | active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); |
c519b5e1 | 833 | |
6cdfb6e6 RS |
834 | if (active == WAIT_FAILED) |
835 | { | |
836 | DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n", | |
837 | nh, timeout_ms, GetLastError ())); | |
c519b5e1 GV |
838 | /* don't return EBADF - this causes wait_reading_process_input to |
839 | abort; WAIT_FAILED is returned when single-stepping under | |
840 | Windows 95 after switching thread focus in debugger, and | |
841 | possibly at other times. */ | |
842 | errno = EINTR; | |
6cdfb6e6 RS |
843 | return -1; |
844 | } | |
845 | else if (active == WAIT_TIMEOUT) | |
846 | { | |
847 | return 0; | |
848 | } | |
849 | else if (active >= WAIT_OBJECT_0 && | |
850 | active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) | |
851 | { | |
852 | active -= WAIT_OBJECT_0; | |
853 | } | |
854 | else if (active >= WAIT_ABANDONED_0 && | |
855 | active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) | |
856 | { | |
857 | active -= WAIT_ABANDONED_0; | |
858 | } | |
6cdfb6e6 | 859 | |
c519b5e1 GV |
860 | /* Loop over all handles after active (now officially documented as |
861 | being the first signalled handle in the array). We do this to | |
862 | ensure fairness, so that all channels with data available will be | |
863 | processed - otherwise higher numbered channels could be starved. */ | |
864 | do | |
6cdfb6e6 | 865 | { |
c519b5e1 GV |
866 | if (fdindex[active] == 0) |
867 | { | |
868 | /* Keyboard input available */ | |
869 | FD_SET (0, rfds); | |
6cdfb6e6 | 870 | nr++; |
c519b5e1 | 871 | } |
6cdfb6e6 | 872 | else |
c519b5e1 GV |
873 | { |
874 | /* must be a socket or pipe */ | |
875 | int current_status; | |
876 | ||
877 | cp = fd_info[ fdindex[active] ].cp; | |
878 | ||
879 | /* Read ahead should have completed, either succeeding or failing. */ | |
880 | FD_SET (fdindex[active], rfds); | |
881 | nr++; | |
882 | current_status = cp->status; | |
883 | if (current_status != STATUS_READ_SUCCEEDED) | |
884 | { | |
885 | if (current_status != STATUS_READ_FAILED) | |
886 | DebPrint (("internal error: subprocess pipe signalled " | |
887 | "at the wrong time (status %d)\n!", current_status)); | |
888 | ||
889 | /* The child_process entry for a socket or pipe will be | |
890 | freed when the last descriptor using it is closed; for | |
891 | pipes, we call the SIGCHLD handler. */ | |
892 | if (fd_info[ fdindex[active] ].flags & FILE_PIPE) | |
893 | { | |
894 | /* The SIGCHLD handler will do a Wait so we know it won't | |
895 | return until the process is dead | |
896 | We force Wait to only wait for this process to avoid it | |
897 | picking up other children that happen to be dead but that | |
898 | we haven't noticed yet | |
899 | SIG_DFL for SIGCHLD is ignore? */ | |
900 | if (sig_handlers[SIGCHLD] != SIG_DFL && | |
901 | sig_handlers[SIGCHLD] != SIG_IGN) | |
902 | { | |
6cdfb6e6 | 903 | #ifdef FULL_DEBUG |
c519b5e1 GV |
904 | DebPrint (("select calling SIGCHLD handler for pid %d\n", |
905 | cp->pid)); | |
6cdfb6e6 | 906 | #endif |
c519b5e1 GV |
907 | dead_child = cp; |
908 | sig_handlers[SIGCHLD] (SIGCHLD); | |
909 | dead_child = NULL; | |
910 | } | |
911 | ||
912 | /* Clean up the child process entry in the table */ | |
913 | reap_subprocess (cp); | |
914 | } | |
915 | } | |
916 | } | |
917 | ||
918 | /* Test for input on remaining channels. */ | |
919 | while (++active < nh) | |
920 | if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0) | |
921 | break; | |
922 | } while (active < nh); | |
923 | ||
6cdfb6e6 RS |
924 | return nr; |
925 | } | |
926 | ||
c519b5e1 | 927 | /* Substitute for certain kill () operations */ |
6cdfb6e6 | 928 | int |
c519b5e1 | 929 | sys_kill (int pid, int sig) |
6cdfb6e6 RS |
930 | { |
931 | child_process *cp; | |
c519b5e1 GV |
932 | HANDLE proc_hand; |
933 | int need_to_free = 0; | |
934 | int rc = 0; | |
6cdfb6e6 RS |
935 | |
936 | /* Only handle signals that will result in the process dying */ | |
937 | if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP) | |
938 | { | |
939 | errno = EINVAL; | |
940 | return -1; | |
941 | } | |
c519b5e1 | 942 | |
6cdfb6e6 RS |
943 | cp = find_child_pid (pid); |
944 | if (cp == NULL) | |
945 | { | |
c519b5e1 GV |
946 | proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid); |
947 | if (proc_hand == NULL) | |
948 | { | |
949 | errno = EPERM; | |
950 | return -1; | |
951 | } | |
952 | need_to_free = 1; | |
953 | } | |
954 | else | |
955 | { | |
956 | proc_hand = cp->procinfo.hProcess; | |
957 | pid = cp->procinfo.dwProcessId; | |
6cdfb6e6 RS |
958 | } |
959 | ||
960 | if (sig == SIGINT) | |
961 | { | |
c519b5e1 | 962 | /* Ctrl-Break is NT equivalent of SIGINT. */ |
6cdfb6e6 RS |
963 | if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid)) |
964 | { | |
c519b5e1 | 965 | DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d " |
6cdfb6e6 RS |
966 | "for pid %lu\n", GetLastError (), pid)); |
967 | errno = EINVAL; | |
c519b5e1 | 968 | rc = -1; |
6cdfb6e6 RS |
969 | } |
970 | } | |
971 | else | |
972 | { | |
973 | /* Kill the process. On Win32 this doesn't kill child processes | |
974 | so it doesn't work very well for shells which is why it's | |
975 | not used in every case. */ | |
c519b5e1 | 976 | if (!TerminateProcess (proc_hand, 0xff)) |
6cdfb6e6 | 977 | { |
c519b5e1 | 978 | DebPrint (("sys_kill.TerminateProcess returned %d " |
6cdfb6e6 RS |
979 | "for pid %lu\n", GetLastError (), pid)); |
980 | errno = EINVAL; | |
c519b5e1 | 981 | rc = -1; |
6cdfb6e6 RS |
982 | } |
983 | } | |
c519b5e1 GV |
984 | |
985 | if (need_to_free) | |
986 | CloseHandle (proc_hand); | |
987 | ||
988 | return rc; | |
6cdfb6e6 RS |
989 | } |
990 | ||
c519b5e1 GV |
991 | extern int report_file_error (char *, Lisp_Object); |
992 | ||
993 | /* The following two routines are used to manipulate stdin, stdout, and | |
994 | stderr of our child processes. | |
995 | ||
996 | Assuming that in, out, and err are *not* inheritable, we make them | |
997 | stdin, stdout, and stderr of the child as follows: | |
998 | ||
999 | - Save the parent's current standard handles. | |
1000 | - Set the std handles to inheritable duplicates of the ones being passed in. | |
1001 | (Note that _get_osfhandle() is an io.h procedure that retrieves the | |
1002 | NT file handle for a crt file descriptor.) | |
1003 | - Spawn the child, which inherits in, out, and err as stdin, | |
1004 | stdout, and stderr. (see Spawnve) | |
1005 | - Close the std handles passed to the child. | |
1006 | - Reset the parent's standard handles to the saved handles. | |
1007 | (see reset_standard_handles) | |
1008 | We assume that the caller closes in, out, and err after calling us. */ | |
1009 | ||
1010 | void | |
1011 | prepare_standard_handles (int in, int out, int err, HANDLE handles[3]) | |
6cdfb6e6 | 1012 | { |
c519b5e1 GV |
1013 | HANDLE parent; |
1014 | HANDLE newstdin, newstdout, newstderr; | |
1015 | ||
1016 | parent = GetCurrentProcess (); | |
1017 | ||
1018 | handles[0] = GetStdHandle (STD_INPUT_HANDLE); | |
1019 | handles[1] = GetStdHandle (STD_OUTPUT_HANDLE); | |
1020 | handles[2] = GetStdHandle (STD_ERROR_HANDLE); | |
1021 | ||
1022 | /* make inheritable copies of the new handles */ | |
1023 | if (!DuplicateHandle (parent, | |
1024 | (HANDLE) _get_osfhandle (in), | |
1025 | parent, | |
1026 | &newstdin, | |
1027 | 0, | |
1028 | TRUE, | |
1029 | DUPLICATE_SAME_ACCESS)) | |
1030 | report_file_error ("Duplicating input handle for child", Qnil); | |
6cdfb6e6 | 1031 | |
c519b5e1 GV |
1032 | if (!DuplicateHandle (parent, |
1033 | (HANDLE) _get_osfhandle (out), | |
1034 | parent, | |
1035 | &newstdout, | |
1036 | 0, | |
1037 | TRUE, | |
1038 | DUPLICATE_SAME_ACCESS)) | |
1039 | report_file_error ("Duplicating output handle for child", Qnil); | |
6cdfb6e6 | 1040 | |
c519b5e1 GV |
1041 | if (!DuplicateHandle (parent, |
1042 | (HANDLE) _get_osfhandle (err), | |
1043 | parent, | |
1044 | &newstderr, | |
1045 | 0, | |
1046 | TRUE, | |
1047 | DUPLICATE_SAME_ACCESS)) | |
1048 | report_file_error ("Duplicating error handle for child", Qnil); | |
1049 | ||
1050 | /* and store them as our std handles */ | |
1051 | if (!SetStdHandle (STD_INPUT_HANDLE, newstdin)) | |
1052 | report_file_error ("Changing stdin handle", Qnil); | |
6cdfb6e6 | 1053 | |
c519b5e1 GV |
1054 | if (!SetStdHandle (STD_OUTPUT_HANDLE, newstdout)) |
1055 | report_file_error ("Changing stdout handle", Qnil); | |
1056 | ||
1057 | if (!SetStdHandle (STD_ERROR_HANDLE, newstderr)) | |
1058 | report_file_error ("Changing stderr handle", Qnil); | |
1059 | } | |
1060 | ||
1061 | void | |
1062 | reset_standard_handles (int in, int out, int err, HANDLE handles[3]) | |
1063 | { | |
1064 | /* close the duplicated handles passed to the child */ | |
1065 | CloseHandle (GetStdHandle (STD_INPUT_HANDLE)); | |
1066 | CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE)); | |
1067 | CloseHandle (GetStdHandle (STD_ERROR_HANDLE)); | |
1068 | ||
1069 | /* now restore parent's saved std handles */ | |
1070 | SetStdHandle (STD_INPUT_HANDLE, handles[0]); | |
1071 | SetStdHandle (STD_OUTPUT_HANDLE, handles[1]); | |
1072 | SetStdHandle (STD_ERROR_HANDLE, handles[2]); | |
6cdfb6e6 | 1073 | } |
c519b5e1 | 1074 | |
93fdf2f8 RS |
1075 | \f |
1076 | syms_of_ntproc () | |
1077 | { | |
1078 | DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args, | |
1079 | "Non-nil enables quoting of process arguments to ensure correct parsing.\n\ | |
1080 | Because Windows does not directly pass argv arrays to child processes,\n\ | |
1081 | programs have to reconstruct the argv array by parsing the command\n\ | |
1082 | line string. For an argument to contain a space, it must be enclosed\n\ | |
1083 | in double quotes or it will be parsed as multiple arguments.\n\ | |
1084 | \n\ | |
1085 | However, the argument list to call-process is not always correctly\n\ | |
1086 | constructed (or arguments have already been quoted), so enabling this\n\ | |
1087 | option may cause unexpected behavior."); | |
1088 | Vwin32_quote_process_args = Qnil; | |
1089 | } | |
c519b5e1 | 1090 | /* end of ntproc.c */ |