Update FSF's address in the preamble.
[bpt/emacs.git] / src / w32proc.c
CommitLineData
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
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
6cdfb6e6
RS
20
21 Drew Bliss Oct 14, 1993
22 Adapted from alarm.c by Tim Fleehart
23*/
24
6816efce
GV
25#include <config.h>
26
6cdfb6e6
RS
27#include <stdio.h>
28#include <stdlib.h>
29#include <errno.h>
30#include <io.h>
31#include <signal.h>
32
6cdfb6e6
RS
33#include <windows.h>
34
35#include "lisp.h"
36#include "nt.h"
37#include "systime.h"
3d7eead0
GV
38#include "syswait.h"
39#include "process.h"
40
41#ifndef SYS_SIGLIST_DECLARED
42extern char *sys_siglist[];
43#endif
6cdfb6e6
RS
44
45/* #define FULL_DEBUG */
46
47typedef void (_CALLBACK_ *signal_handler)(int);
48
49/* Defined in process.h which conflicts with the local copy */
50#define _P_NOWAIT 1
51
52typedef struct _child_process
53{
54 int fd;
55 HANDLE char_avail;
56 HANDLE char_consumed;
57 char chr;
58 BOOL status;
59 HANDLE process;
60 DWORD pid;
61 HANDLE thrd;
62} child_process;
63
64#define MAX_CHILDREN MAXDESC
65
66#ifdef EMACSDEBUG
67void _CRTAPI1
68_DebPrint (char *fmt, ...)
69{
70 char buf[256];
71 va_list args;
72
73 va_start (args, fmt);
74 vsprintf (buf, fmt, args);
75 va_end (args);
76 OutputDebugString (buf);
77}
78#endif
79
80/* Child process management list. */
81static int child_proc_count = 0;
82static child_process child_procs[MAX_CHILDREN];
83static child_process *dead_child = NULL;
84
85#define CHILD_ACTIVE(cp) ((cp)->process != NULL)
86#define DEACTIVATE_CHILD(cp) ((cp)->process = NULL)
87
88/* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
89static signal_handler sig_handlers[NSIG];
90
91/* Fake signal implementation to record the SIGCHLD handler. */
92signal_handler
93win32_signal (int sig, signal_handler handler)
94{
95 signal_handler old;
96
97 if (sig != SIGCHLD)
98 {
99 errno = EINVAL;
100 return SIG_ERR;
101 }
102 old = sig_handlers[sig];
103 sig_handlers[sig] = handler;
104 return old;
105}
106
107/* Find an unused process slot. */
108static child_process *
109new_child (void)
110{
111 child_process *cp;
112
113 if (child_proc_count == MAX_CHILDREN)
114 return NULL;
115
116 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
117 if (!CHILD_ACTIVE (cp))
118 return cp;
119 return &child_procs[child_proc_count++];
120}
121
122/* Find a child by pid. */
123static child_process *
124find_child_pid (DWORD pid)
125{
126 child_process *cp;
127
128 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
129 if (CHILD_ACTIVE (cp) && pid == cp->pid)
130 return cp;
131 return NULL;
132}
133
134/* Find a child by fd. */
135static child_process *
136find_child_fd (int fd)
137{
138 child_process *cp;
139
140 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
141 if (CHILD_ACTIVE (cp) && fd == cp->fd)
142 return cp;
143 return NULL;
144}
145
146/* Thread proc for child process reader threads
147 The threads just sit in a loop waiting for input
148 When they detect input, they signal the char_avail input to
149 wake up the select emulator
150 When the select emulator processes their input, it pulses
151 char_consumed so that the reader thread goes back to reading. */
152DWORD WINAPI
153reader_thread (void *arg)
154{
155 child_process *cp;
156
157 /* Our identity */
158 cp = (child_process *)arg;
159
160 /* We have to wait for the go-ahead before we can start */
161 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
162 return 0;
163 /* If something went wrong, quit */
164 if (!cp->status)
165 return 0;
166
167 for (;;)
168 {
169 /* Use read to get CRLF translation */
170 if (read (cp->fd, &cp->chr, sizeof (char)) == sizeof (char))
171 {
172 cp->status = TRUE;
173 }
174 else
175 {
176#ifdef FULL_DEBUG
177 DebPrint (("reader_thread.read failed with %lu for fd %ld\n",
178 GetLastError (), cp->fd));
179#endif
180 cp->status = FALSE;
181 }
182
183 if (!SetEvent (cp->char_avail))
184 {
185 DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
186 GetLastError (), cp->fd));
187 break;
188 }
189
190 /* If the read died, the child has died so let the thread die */
191 if (!cp->status)
192 break;
193
194 /* Wait until our input is acknowledged before reading again */
195 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
196 {
197 DebPrint (("reader_thread.WaitForSingleObject failed with "
198 "%lu for fd %ld\n", GetLastError (), cp->fd));
199 break;
200 }
201 }
202 return 0;
203}
204
205static BOOL
206create_child (char *exe, char *cmdline, char *env,
207 PROCESS_INFORMATION *info)
208{
209 child_process *cp;
210 DWORD id;
211 STARTUPINFO start;
212 SECURITY_ATTRIBUTES sec_attrs;
213 SECURITY_DESCRIPTOR sec_desc;
214
215 cp = new_child ();
216 if (cp == NULL)
217 goto EH_Fail;
218
219 cp->fd = -1;
220
221 cp->char_avail = CreateEvent (NULL, FALSE, FALSE, NULL);
222 if (cp->char_avail == NULL)
223 goto EH_Fail;
224
225 cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
226 if (cp->char_consumed == NULL)
227 goto EH_char_avail;
228
229 cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
230 if (cp->thrd == NULL)
231 goto EH_char_consumed;
232
233 memset (&start, 0, sizeof (start));
234 start.cb = sizeof (start);
235
58d4e829
GV
236#ifdef HAVE_NTGUI
237 start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
238 start.wShowWindow = SW_HIDE;
239
240 start.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
241 start.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
242 start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
243#endif /* HAVE_NTGUI */
244
6cdfb6e6
RS
245 /* Explicitly specify no security */
246 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
247 goto EH_thrd;
248 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
249 goto EH_thrd;
250 sec_attrs.nLength = sizeof (sec_attrs);
251 sec_attrs.lpSecurityDescriptor = &sec_desc;
252 sec_attrs.bInheritHandle = FALSE;
253
254 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
255 CREATE_NEW_PROCESS_GROUP, env, NULL,
256 &start, info))
257 goto EH_thrd;
258 cp->process = info->hProcess;
259 cp->pid = info->dwProcessId;
260
261 return TRUE;
262
263 EH_thrd:
264 id = GetLastError ();
265
266 cp->status = FALSE;
267 SetEvent (cp->char_consumed);
268 EH_char_consumed:
269 CloseHandle (cp->char_consumed);
270 EH_char_avail:
271 CloseHandle (cp->char_avail);
272 EH_Fail:
273 return FALSE;
274}
275
276/* create_child doesn't know what emacs' file handle will be for waiting
277 on output from the child, so we need to make this additional call
278 to register the handle with the process
279 This way the select emulator knows how to match file handles with
280 entries in child_procs. */
281void
282register_child (int pid, int fd)
283{
284 child_process *cp;
285
286 cp = find_child_pid (pid);
287 if (cp == NULL)
288 {
289 DebPrint (("register_child unable to find pid %lu\n", pid));
290 return;
291 }
292
293#ifdef FULL_DEBUG
294 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid));
295#endif
296
297 cp->fd = fd;
298 cp->status = TRUE;
299
300 /* Tell the reader thread to start */
301 if (!SetEvent (cp->char_consumed))
302 {
303 DebPrint (("register_child.SetEvent failed with %lu for fd %ld\n",
304 GetLastError (), cp->fd));
305 }
306}
307
308/* When a process dies its pipe will break so the reader thread will
309 signal failure to the select emulator.
310 The select emulator then calls this routine to clean up.
311 Since the thread signaled failure we can assume it is exiting. */
312static void
313remove_child (child_process *cp)
314{
315 /* Reap the thread */
316 if (WaitForSingleObject (cp->thrd, INFINITE) != WAIT_OBJECT_0)
317 {
318 DebPrint (("remove_child.WaitForSingleObject (thread) failed "
319 "with %lu for fd %ld\n", GetLastError (), cp->fd));
320 }
321 CloseHandle (cp->thrd);
322 CloseHandle (cp->char_consumed);
323 CloseHandle (cp->char_avail);
324
325 /* Reap the process */
326 if (WaitForSingleObject (cp->process, INFINITE) != WAIT_OBJECT_0)
327 {
328 DebPrint (("remove_child.WaitForSingleObject (process) failed "
329 "with %lu for fd %ld\n", GetLastError (), cp->fd));
330 }
331 CloseHandle (cp->process);
332
333 DEACTIVATE_CHILD (cp);
334}
335
336/* Wait for any of our existing child processes to die
337 When it does, close its handle
338 Return the pid and fill in the status if non-NULL. */
22759c72 339
6cdfb6e6
RS
340int
341win32_wait (int *status)
342{
343 DWORD active, retval;
344 int nh;
345 child_process *cp, *cps[MAX_CHILDREN];
346 HANDLE wait_hnd[MAX_CHILDREN];
347
348 nh = 0;
349 if (dead_child != NULL)
350 {
351 /* We want to wait for a specific child */
352 wait_hnd[nh] = dead_child->process;
353 cps[nh] = dead_child;
354 nh++;
355 }
356 else
357 {
358 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
359 if (CHILD_ACTIVE (cp))
360 {
361 wait_hnd[nh] = cp->process;
362 cps[nh] = cp;
363 nh++;
364 }
365 }
366
367 if (nh == 0)
368 {
369 /* Nothing to wait on, so fail */
370 errno = ECHILD;
371 return -1;
372 }
373
374 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, INFINITE);
375 if (active == WAIT_FAILED)
376 {
377 errno = EBADF;
378 return -1;
379 }
380 else if (active == WAIT_TIMEOUT)
381 {
382 /* Should never happen */
383 errno = EINVAL;
384 return -1;
385 }
386 else if (active >= WAIT_OBJECT_0 &&
387 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
388 {
389 active -= WAIT_OBJECT_0;
390 }
391 else if (active >= WAIT_ABANDONED_0 &&
392 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
393 {
394 active -= WAIT_ABANDONED_0;
395 }
396
397 if (!GetExitCodeProcess (wait_hnd[active], &retval))
398 {
399 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n",
400 GetLastError ()));
401 retval = 1;
402 }
403 if (retval == STILL_ACTIVE)
404 {
405 /* Should never happen */
406 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
407 errno = EINVAL;
408 return -1;
409 }
bc69349b
RS
410
411 /* Massage the exit code from the process to match the format expected
8e6208c5 412 by the WIFSTOPPED et al macros in syswait.h. Only WIFSIGNALED and
bc69349b
RS
413 WIFEXITED are supported; WIFSTOPPED doesn't make sense under NT. */
414
415 if (retval == STATUS_CONTROL_C_EXIT)
416 retval = SIGINT;
417 else
418 retval <<= 8;
419
6cdfb6e6 420 cp = cps[active];
22759c72 421
6cdfb6e6
RS
422 if (status)
423 {
22759c72
KH
424 *status = retval;
425 }
426 else if (synch_process_alive)
427 {
428 synch_process_alive = 0;
22759c72 429
3d7eead0
GV
430 /* Report the status of the synchronous process. */
431 if (WIFEXITED (retval))
432 synch_process_retcode = WRETCODE (retval);
433 else if (WIFSIGNALED (retval))
434 {
435 int code = WTERMSIG (retval);
436 char *signame = 0;
437
438 if (code < NSIG)
439 {
440 /* Suppress warning if the table has const char *. */
441 signame = (char *) sys_siglist[code];
442 }
443 if (signame == 0)
444 signame = "unknown";
445
446 synch_process_death = signame;
447 }
22759c72
KH
448 TerminateThread (cp->thrd, 0);
449 CloseHandle (cp->thrd);
450 CloseHandle (cp->char_consumed);
451 CloseHandle (cp->char_avail);
452 CloseHandle (cp->process);
453 DEACTIVATE_CHILD (cp);
6cdfb6e6
RS
454 }
455
456 return cp->pid;
457}
458
459/* We pass our process ID to our children by setting up an environment
460 variable in their environment. */
461char ppid_env_var_buffer[64];
462
463/* When a new child process is created we need to register it in our list,
464 so intercept spawn requests. */
465int
466win32_spawnve (int mode, char *cmdname, char **argv, char **envp)
467{
0a4de642 468 Lisp_Object program, full;
6cdfb6e6
RS
469 char *cmdline, *env, *parg, **targ;
470 int arglen;
471 PROCESS_INFORMATION pi;
0a4de642
RS
472
473 /* Handle executable names without an executable suffix. */
474 program = make_string (cmdname, strlen (cmdname));
475 if (NILP (Ffile_executable_p (program)))
476 {
477 struct gcpro gcpro1;
478
479 full = Qnil;
480 GCPRO1 (program);
481 openp (Vexec_path, program, EXEC_SUFFIXES, &full, 1);
482 UNGCPRO;
483 if (NILP (full))
484 {
485 errno = EINVAL;
486 return -1;
487 }
488 cmdname = XSTRING (full)->data;
489 argv[0] = cmdname;
490 }
491
6cdfb6e6
RS
492 if (child_proc_count == MAX_CHILDREN)
493 {
494 errno = EAGAIN;
495 return -1;
496 }
497
498 /* We don't care about the other modes */
499 if (mode != _P_NOWAIT)
500 {
501 errno = EINVAL;
502 return -1;
503 }
504
505 /* we have to do some conjuring here to put argv and envp into the
506 form CreateProcess wants... argv needs to be a space separated/null
507 terminated list of parameters, and envp is a null
508 separated/double-null terminated list of parameters.
509
510 Since I have no idea how large argv and envp are likely to be
511 we figure out list lengths on the fly and allocate them. */
512
513 /* do argv... */
514 arglen = 0;
515 targ = argv;
516 while (*targ)
517 {
518 arglen += strlen (*targ++) + 1;
519 }
520 cmdline = malloc (arglen);
521 if (cmdline == NULL)
522 {
523 errno = ENOMEM;
524 goto EH_Fail;
525 }
526 targ = argv;
527 parg = cmdline;
528 while (*targ)
529 {
530 strcpy (parg, *targ);
531 parg += strlen (*targ++);
532 *parg++ = ' ';
533 }
534 *--parg = '\0';
535
536 /* and envp... */
537 arglen = 1;
538 targ = envp;
539 while (*targ)
540 {
541 arglen += strlen (*targ++) + 1;
542 }
543 sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d",
544 GetCurrentProcessId ());
545 arglen += strlen (ppid_env_var_buffer) + 1;
546
547 env = malloc (arglen);
548 if (env == NULL)
549 {
550 errno = ENOMEM;
551 goto EH_cmdline;
552 }
553 targ = envp;
554 parg = env;
555 while (*targ)
556 {
557 strcpy (parg, *targ);
558 parg += strlen (*targ++);
559 *parg++ = '\0';
560 }
561 strcpy (parg, ppid_env_var_buffer);
562 parg += strlen (ppid_env_var_buffer);
563 *parg++ = '\0';
564 *parg = '\0';
565
566 /* Now create the process. */
567 if (!create_child (cmdname, cmdline, env, &pi))
568 {
569 errno = ENOEXEC;
570 goto EH_env;
571 }
572
573 return pi.dwProcessId;
574
575 EH_env:
576 free (env);
577 EH_cmdline:
578 free (cmdline);
579 EH_Fail:
580 return -1;
581}
582
583/* Emulate the select call
584 Wait for available input on any of the given rfds, or timeout if
585 a timeout is given and no input is detected
586 wfds and efds are not supported and must be NULL. */
587
588/* From ntterm.c */
589extern HANDLE keyboard_handle;
590/* From process.c */
591extern int proc_buffered_char[];
592
593int
22759c72
KH
594sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
595 EMACS_TIME *timeout)
6cdfb6e6
RS
596{
597 SELECT_TYPE orfds;
598 DWORD timeout_ms;
599 int i, nh, nr;
600 DWORD active;
58d4e829
GV
601 child_process *cp, *cps[MAX_CHILDREN + 1];
602 HANDLE wait_hnd[MAX_CHILDREN + 1];
603#ifdef HAVE_NTGUI1
604 BOOL keyboardwait = FALSE ;
605#endif /* HAVE_NTGUI */
6cdfb6e6
RS
606
607 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
608 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL)
609 {
22759c72
KH
610#ifdef HAVE_TIMEVAL
611 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
612#else
6cdfb6e6 613 Sleep ((*timeout) * 1000);
22759c72 614#endif
6cdfb6e6
RS
615 return 0;
616 }
617
618 /* Otherwise, we only handle rfds, so fail otherwise. */
619 if (rfds == NULL || wfds != NULL || efds != NULL)
620 {
621 errno = EINVAL;
622 return -1;
623 }
624
625 orfds = *rfds;
626 FD_ZERO (rfds);
627 nr = 0;
628
629 /* Build a list of handles to wait on. */
630 nh = 0;
631 for (i = 0; i < nfds; i++)
632 if (FD_ISSET (i, &orfds))
633 {
634 if (i == 0)
635 {
58d4e829
GV
636#ifdef HAVE_NTGUI1
637 keyboardwait = TRUE ;
638#else
6cdfb6e6
RS
639 /* Handle stdin specially */
640 wait_hnd[nh] = keyboard_handle;
641 cps[nh] = NULL;
642 nh++;
58d4e829 643#endif /* HAVE_NTGUI */
6cdfb6e6
RS
644
645 /* Check for any emacs-generated input in the queue since
646 it won't be detected in the wait */
647 if (detect_input_pending ())
648 {
649 FD_SET (i, rfds);
650 nr++;
651 }
652 }
653 else
654 {
655 /* Child process input */
656 cp = find_child_fd (i);
657 if (cp)
658 {
659#ifdef FULL_DEBUG
660 DebPrint (("select waiting on child %d fd %d\n",
661 cp-child_procs, i));
662#endif
663 wait_hnd[nh] = cp->char_avail;
664 cps[nh] = cp;
665 nh++;
666 }
667 else
668 {
669 /* Unable to find something to wait on for this fd, fail */
670 DebPrint (("select unable to find child process "
671 "for fd %ld\n", i));
672 nh = 0;
673 break;
674 }
675 }
676 }
677
58d4e829
GV
678 /* Never do this in win32 since we will not get paint messages */
679
680#ifndef HAVE_NTGUI1
6cdfb6e6
RS
681 /* Nothing to look for, so we didn't find anything */
682 if (nh == 0)
683 {
22759c72
KH
684 if (timeout)
685#ifdef HAVE_TIMEVAL
686 Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
687#else
688 Sleep ((*timeout) * 1000);
689#endif
6cdfb6e6
RS
690 return 0;
691 }
58d4e829 692#endif /* !HAVE_NTGUI */
6cdfb6e6
RS
693
694 /* Check for immediate return without waiting */
695 if (nr > 0)
696 return nr;
697
698 /*
699 Wait for input
700 If a child process dies while this is waiting, its pipe will break
701 so the reader thread will signal an error condition, thus, the wait
702 will wake up
703 */
22759c72
KH
704#ifdef HAVE_TIMEVAL
705 timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE;
706#else
6cdfb6e6 707 timeout_ms = timeout ? *timeout*1000 : INFINITE;
22759c72 708#endif
58d4e829
GV
709#ifdef HAVE_NTGUI1
710 active = MsgWaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms,QS_ALLINPUT);
711#else
6cdfb6e6 712 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms);
58d4e829 713#endif /* HAVE_NTGUI */
6cdfb6e6
RS
714 if (active == WAIT_FAILED)
715 {
716 DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
717 nh, timeout_ms, GetLastError ()));
718 /* Is there a better error? */
719 errno = EBADF;
720 return -1;
721 }
722 else if (active == WAIT_TIMEOUT)
723 {
724 return 0;
725 }
58d4e829
GV
726#ifdef HAVE_NTGUI1
727 else if (active == WAIT_OBJECT_0 + nh)
728 {
729 /* Keyboard input available */
730 FD_SET (0, rfds);
731
732 /* This shouldn't be necessary, but apparently just setting the input
733 fd is not good enough for emacs */
734// read_input_waiting ();
735
736 return (1) ;
737 }
738#endif /* HAVE_NTGUI */
6cdfb6e6
RS
739 else if (active >= WAIT_OBJECT_0 &&
740 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
741 {
742 active -= WAIT_OBJECT_0;
743 }
744 else if (active >= WAIT_ABANDONED_0 &&
745 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
746 {
747 active -= WAIT_ABANDONED_0;
748 }
749
750 if (cps[active] == NULL)
751 {
752 /* Keyboard input available */
753 FD_SET (0, rfds);
754 nr++;
755
756 /* This shouldn't be necessary, but apparently just setting the input
757 fd is not good enough for emacs */
758 read_input_waiting ();
759 }
760 else
761 {
762 /* Child process */
763 cp = cps[active];
764
765 /* If status is FALSE the read failed so don't report input */
766 if (cp->status)
767 {
768 FD_SET (cp->fd, rfds);
769 proc_buffered_char[cp->fd] = cp->chr;
770 nr++;
771 }
772 else
773 {
774 /* The SIGCHLD handler will do a Wait so we know it won't
775 return until the process is dead
776 We force Wait to only wait for this process to avoid it
777 picking up other children that happen to be dead but that
778 we haven't noticed yet
779 SIG_DFL for SIGCHLD is ignore? */
780 if (sig_handlers[SIGCHLD] != SIG_DFL &&
781 sig_handlers[SIGCHLD] != SIG_IGN)
782 {
783#ifdef FULL_DEBUG
784 DebPrint (("select calling SIGCHLD handler for pid %d\n",
785 cp->pid));
786#endif
787 dead_child = cp;
788 sig_handlers[SIGCHLD](SIGCHLD);
789 dead_child = NULL;
790 }
791
792 /* Clean up the child process entry in the table */
793 remove_child (cp);
794 }
795 }
796 return nr;
797}
798
799/*
800 Substitute for certain kill () operations
801 */
802int
803win32_kill_process (int pid, int sig)
804{
805 child_process *cp;
806
807 /* Only handle signals that will result in the process dying */
808 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
809 {
810 errno = EINVAL;
811 return -1;
812 }
813
814 cp = find_child_pid (pid);
815 if (cp == NULL)
816 {
817 DebPrint (("win32_kill_process didn't find a child with pid %lu\n", pid));
818 errno = ECHILD;
819 return -1;
820 }
821
822 if (sig == SIGINT)
823 {
824 /* Fake Ctrl-Break. */
825 if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
826 {
827 DebPrint (("win32_kill_process.GenerateConsoleCtrlEvent return %d "
828 "for pid %lu\n", GetLastError (), pid));
829 errno = EINVAL;
830 return -1;
831 }
832 }
833 else
834 {
835 /* Kill the process. On Win32 this doesn't kill child processes
836 so it doesn't work very well for shells which is why it's
837 not used in every case. */
838 if (!TerminateProcess (cp->process, 0xff))
839 {
840 DebPrint (("win32_kill_process.TerminateProcess returned %d "
841 "for pid %lu\n", GetLastError (), pid));
842 errno = EINVAL;
843 return -1;
844 }
845 }
846 return 0;
847}
848
849/* If the channel is a pipe this read might block since we don't
850 know how many characters are available, so check and read only
851 what's there
852 We also need to wake up the reader thread once we've read our data. */
853int
854read_child_output (int fd, char *buf, int max)
855{
856 HANDLE h;
857 int to_read, nchars;
858 DWORD waiting;
859 child_process *cp;
860
861 h = (HANDLE)_get_osfhandle (fd);
862 if (GetFileType (h) == FILE_TYPE_PIPE)
863 {
864 PeekNamedPipe (h, NULL, 0, NULL, &waiting, NULL);
865 to_read = min (waiting, (DWORD)max);
866 }
867 else
868 to_read = max;
869
870 /* Use read to get CRLF translation */
871 nchars = read (fd, buf, to_read);
872
873 if (GetFileType (h) == FILE_TYPE_PIPE)
874 {
875 /* Wake up the reader thread
876 for this process */
877 cp = find_child_fd (fd);
878 if (cp)
879 {
880 if (!SetEvent (cp->char_consumed))
881 DebPrint (("read_child_output.SetEvent failed with "
882 "%lu for fd %ld\n", GetLastError (), fd));
883 }
884 else
885 DebPrint (("read_child_output couldn't find a child with fd %d\n",
886 fd));
887 }
888
889 return nchars;
890}