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