OSDN Git Service

* debug.h (console_printf): Define for non-debugging condition.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / spawn.cc
1 /* spawn.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include "winsup.h"
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <unistd.h>
15 #include <process.h>
16 #include <sys/wait.h>
17 #include <limits.h>
18 #include <wingdi.h>
19 #include <winuser.h>
20 #include <ctype.h>
21 #include "cygerrno.h"
22 #include <sys/cygwin.h>
23 #include "security.h"
24 #include "path.h"
25 #include "fhandler.h"
26 #include "dtable.h"
27 #include "sigproc.h"
28 #include "cygheap.h"
29 #include "child_info.h"
30 #include "shared_info.h"
31 #include "pinfo.h"
32 #define NEED_VFORK
33 #include "perthread.h"
34 #include "registry.h"
35 #include "environ.h"
36 #include "cygthread.h"
37
38 #define LINE_BUF_CHUNK (CYG_MAX_PATH * 2)
39
40 static suffix_info std_suffixes[] =
41 {
42   suffix_info (".exe", 1), suffix_info ("", 1),
43   suffix_info (".com"), suffix_info (".cmd"),
44   suffix_info (".bat"), suffix_info (".dll"),
45   suffix_info (NULL)
46 };
47
48 HANDLE hExeced;
49 DWORD dwExeced;
50
51 /* Add .exe to PROG if not already present and see if that exists.
52    If not, return PROG (converted from posix to win32 rules if necessary).
53    The result is always BUF.
54
55    Returns (possibly NULL) suffix */
56
57 static const char *
58 perhaps_suffix (const char *prog, path_conv& buf)
59 {
60   char *ext;
61
62   debug_printf ("prog '%s'", prog);
63   buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes);
64
65   if (!buf.exists () || buf.isdir ())
66     ext = NULL;
67   else if (buf.known_suffix)
68     ext = (char *) buf + (buf.known_suffix - buf.get_win32 ());
69   else
70     ext = strchr (buf, '\0');
71
72   debug_printf ("buf %s, suffix found '%s'", (char *) buf, ext);
73   return ext;
74 }
75
76 /* Find an executable name, possibly by appending known executable
77    suffixes to it.  The win32-translated name is placed in 'buf'.
78    Any found suffix is returned in known_suffix.
79
80    If the file is not found and !null_if_not_found then the win32 version
81    of name is placed in buf and returned.  Otherwise the contents of buf
82    is undefined and NULL is returned.  */
83
84 const char * __stdcall
85 find_exec (const char *name, path_conv& buf, const char *mywinenv,
86            unsigned opt, const char **known_suffix)
87 {
88   const char *suffix = "";
89   debug_printf ("find_exec (%s)", name);
90   const char *retval = buf;
91   char tmp[CYG_MAX_PATH];
92   const char *posix = (opt & FE_NATIVE) ? NULL : name;
93   bool has_slash = strchr (name, '/');
94
95   /* Check to see if file can be opened as is first.
96      Win32 systems always check . first, but PATH may not be set up to
97      do this. */
98   if ((has_slash || opt & FE_CWD)
99       && (suffix = perhaps_suffix (name, buf)) != NULL)
100     {
101       if (posix && !has_slash)
102         {
103           tmp[0] = '.';
104           tmp[1] = '/';
105           strcpy (tmp + 2, name);
106           posix = tmp;
107         }
108       goto out;
109     }
110
111   win_env *winpath;
112   const char *path;
113   const char *posix_path;
114
115   /* Return the error condition if this is an absolute path or if there
116      is no PATH to search. */
117   if (strchr (name, '/') || strchr (name, '\\') ||
118       isdrive (name) ||
119       !(winpath = getwinenv (mywinenv)) ||
120       !(path = winpath->get_native ()) ||
121       *path == '\0')
122     goto errout;
123
124   debug_printf ("%s%s", mywinenv, path);
125
126   posix = (opt & FE_NATIVE) ? NULL : tmp;
127   posix_path = winpath->get_posix () - 1;
128   /* Iterate over the specified path, looking for the file with and
129      without executable extensions. */
130   do
131     {
132       posix_path++;
133       char *eotmp = strccpy (tmp, &path, ';');
134       /* An empty path or '.' means the current directory, but we've
135          already tried that.  */
136       if (opt & FE_CWD && (tmp[0] == '\0' || (tmp[0] == '.' && tmp[1] == '\0')))
137         continue;
138
139       *eotmp++ = '\\';
140       strcpy (eotmp, name);
141
142       debug_printf ("trying %s", tmp);
143
144       if ((suffix = perhaps_suffix (tmp, buf)) != NULL)
145         {
146           if (posix == tmp)
147             {
148               eotmp = strccpy (tmp, &posix_path, ':');
149               if (eotmp == tmp)
150                 *eotmp++ = '.';
151               *eotmp++ = '/';
152               strcpy (eotmp, name);
153             }
154           goto out;
155         }
156     }
157   while (*path && *++path && (posix_path = strchr (posix_path, ':')));
158
159  errout:
160   posix = NULL;
161   /* Couldn't find anything in the given path.
162      Take the appropriate action based on null_if_not_found. */
163   if (opt & FE_NNF)
164     retval = NULL;
165   else if (opt & FE_NATIVE)
166     buf.check (name);
167   else
168     retval = name;
169
170  out:
171   if (posix)
172     buf.set_path (posix);
173   debug_printf ("%s = find_exec (%s)", (char *) buf, name);
174   if (known_suffix)
175     *known_suffix = suffix ?: strchr (buf, '\0');
176   return retval;
177 }
178
179 /* Utility for spawn_guts.  */
180
181 static HANDLE
182 handle (int n, int direction)
183 {
184   fhandler_base *fh = cygheap->fdtab[n];
185
186   if (!fh)
187     return INVALID_HANDLE_VALUE;
188   if (fh->get_close_on_exec ())
189     return INVALID_HANDLE_VALUE;
190   if (direction == 0)
191     return fh->get_handle ();
192   return fh->get_output_handle ();
193 }
194
195 int
196 iscmd (const char *argv0, const char *what)
197 {
198   int n;
199   n = strlen (argv0) - strlen (what);
200   if (n >= 2 && argv0[1] != ':')
201     return 0;
202   return n >= 0 && strcasematch (argv0 + n, what) &&
203          (n == 0 || isdirsep (argv0[n - 1]));
204 }
205
206 class linebuf
207 {
208  public:
209   size_t ix;
210   char *buf;
211   size_t alloced;
212   linebuf () : ix (0), buf (NULL), alloced (0) {}
213   ~linebuf () {if (buf) free (buf);}
214   void add (const char *what, int len);
215   void add (const char *what) {add (what, strlen (what));}
216   void prepend (const char *what, int len);
217 };
218
219 void
220 linebuf::add (const char *what, int len)
221 {
222   size_t newix;
223   if ((newix = ix + len) >= alloced || !buf)
224     {
225       alloced += LINE_BUF_CHUNK + newix;
226       buf = (char *) realloc (buf, alloced + 1);
227     }
228   memcpy (buf + ix, what, len);
229   ix = newix;
230   buf[ix] = '\0';
231 }
232
233 void
234 linebuf::prepend (const char *what, int len)
235 {
236   int buflen;
237   size_t newix;
238   if ((newix = ix + len) >= alloced)
239     {
240       alloced += LINE_BUF_CHUNK + newix;
241       buf = (char *) realloc (buf, alloced + 1);
242       buf[ix] = '\0';
243     }
244   if ((buflen = strlen (buf)))
245       memmove (buf + len, buf, buflen + 1);
246   else
247       buf[newix] = '\0';
248   memcpy (buf, what, len);
249   ix = newix;
250 }
251
252 class av
253 {
254   char **argv;
255   int calloced;
256  public:
257   int error;
258   int argc;
259   av (int ac, const char * const *av) : calloced (0), error (false), argc (ac)
260   {
261     argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 5) * sizeof (char *));
262     memcpy (argv, av, (argc + 1) * sizeof (char *));
263   }
264   ~av ()
265   {
266     if (argv)
267       {
268         for (int i = 0; i < calloced; i++)
269           if (argv[i])
270             cfree (argv[i]);
271         cfree (argv);
272       }
273   }
274   int unshift (const char *what, int conv = 0);
275   operator char **() {return argv;}
276   void all_calloced () {calloced = argc;}
277   void replace0_maybe (const char *arg0)
278   {
279     /* Note: Assumes that argv array has not yet been "unshifted" */
280     if (!calloced
281         && (argv[0] = cstrdup1 (arg0)))
282       calloced = true;
283     else
284       error = errno;
285   }
286   void dup_maybe (int i)
287   {
288     if (i >= calloced
289         && !(argv[i] = cstrdup1 (argv[i])))
290       error = errno;
291   }
292   void dup_all ()
293   {
294     for (int i = calloced; i < argc; i++)
295       if (!(argv[i] = cstrdup1 (argv[i])))
296         error = errno;
297   }
298 };
299
300 int
301 av::unshift (const char *what, int conv)
302 {
303   char **av;
304   av = (char **) crealloc (argv, (argc + 2) * sizeof (char *));
305   if (!av)
306     return 0;
307
308   argv = av;
309   memmove (argv + 1, argv, (argc + 1) * sizeof (char *));
310   char buf[CYG_MAX_PATH + 1];
311   if (conv)
312     {
313       cygwin_conv_to_posix_path (what, buf);
314       char *p = strchr (buf, '\0') - 4;
315       if (p > buf && strcasematch (p, ".exe"))
316         *p = '\0';
317       what = buf;
318     }
319   if (!(*argv = cstrdup1 (what)))
320     error = errno;
321   argc++;
322   calloced++;
323   return 1;
324 }
325
326 struct pthread_cleanup
327 {
328   _sig_func_ptr oldint;
329   _sig_func_ptr oldquit;
330   sigset_t oldmask;
331   pthread_cleanup (): oldint (NULL), oldquit (NULL), oldmask (0) {}
332 };
333
334 static void
335 do_cleanup (void *args)
336 {
337 # define cleanup ((pthread_cleanup *) args)
338   if (cleanup->oldint)
339     signal (SIGINT, cleanup->oldint);
340   if (cleanup->oldquit)
341     signal (SIGQUIT, cleanup->oldquit);
342   if (cleanup->oldmask)
343     sigprocmask (SIG_SETMASK, &(cleanup->oldmask), NULL);
344 # undef cleanup
345 }
346
347
348 static int __stdcall
349 spawn_guts (const char * prog_arg, const char *const *argv,
350             const char *const envp[], int mode)
351 {
352   bool rc;
353   pid_t cygpid;
354
355   MALLOC_CHECK;
356
357   if (prog_arg == NULL)
358     {
359       syscall_printf ("prog_arg is NULL");
360       set_errno (EINVAL);
361       return -1;
362     }
363
364   syscall_printf ("spawn_guts (%d, %.9500s)", mode, prog_arg);
365
366   if (argv == NULL)
367     {
368       syscall_printf ("argv is NULL");
369       set_errno (EINVAL);
370       return -1;
371     }
372
373   path_conv real_path;
374
375   linebuf one_line;
376
377   STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
378
379   child_info_spawn ciresrv;
380   si.lpReserved2 = (LPBYTE) &ciresrv;
381   si.cbReserved2 = sizeof (ciresrv);
382
383   DWORD chtype;
384   if (mode != _P_OVERLAY)
385     chtype = PROC_SPAWN;
386   else
387     chtype = PROC_EXEC;
388
389   HANDLE subproc_ready;
390   if (chtype != PROC_EXEC)
391     subproc_ready = NULL;
392   else
393     {
394       subproc_ready = CreateEvent (&sec_all, TRUE, FALSE, NULL);
395       ProtectHandleINH (subproc_ready);
396     }
397
398   init_child_info (chtype, &ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1,
399                    subproc_ready);
400
401   ciresrv.moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
402   ciresrv.moreinfo->old_title = NULL;
403
404   /* CreateProcess takes one long string that is the command line (sigh).
405      We need to quote any argument that has whitespace or embedded "'s.  */
406
407   int ac;
408   for (ac = 0; argv[ac]; ac++)
409     /* nothing */;
410
411   av newargv (ac, argv);
412
413   int null_app_name = 0;
414   if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
415       (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
416     {
417       real_path.check (prog_arg);
418       one_line.add ("\"");
419       if (!real_path.error)
420         one_line.add (real_path);
421       else
422         one_line.add (argv[0]);
423       one_line.add ("\"");
424       one_line.add (" ");
425       one_line.add (argv[1]);
426       one_line.add (" ");
427       one_line.add (argv[2]);
428       strcpy (real_path, argv[0]);
429       null_app_name = 1;
430       goto skip_arg_parsing;
431     }
432
433   const char *ext;
434   if ((ext = perhaps_suffix (prog_arg, real_path)) == NULL)
435     {
436       set_errno (ENOENT);
437       return -1;
438     }
439
440   MALLOC_CHECK;
441
442   /* If the file name ends in either .exe, .com, .bat, or .cmd we assume
443      that it is NOT a script file */
444   while (*ext == '\0')
445     {
446       HANDLE hnd = CreateFile (real_path, GENERIC_READ,
447                                FILE_SHARE_READ | FILE_SHARE_WRITE,
448                                &sec_none_nih, OPEN_EXISTING,
449                                FILE_ATTRIBUTE_NORMAL, 0);
450       if (hnd == INVALID_HANDLE_VALUE)
451         {
452           __seterrno ();
453           return -1;
454         }
455
456       DWORD done;
457
458       char buf[2 * CYG_MAX_PATH + 1];
459       buf[0] = buf[1] = buf[2] = buf[sizeof (buf) - 1] = '\0';
460       if (!ReadFile (hnd, buf, sizeof (buf) - 1, &done, 0))
461         {
462           CloseHandle (hnd);
463           __seterrno ();
464           return -1;
465         }
466
467       CloseHandle (hnd);
468
469       if (buf[0] == 'M' && buf[1] == 'Z')
470         break;
471
472       debug_printf ("%s is a script", (char *) real_path);
473
474       char *pgm, *arg1;
475
476       if (buf[0] != '#' || buf[1] != '!')
477         {
478           pgm = (char *) "/bin/sh";
479           arg1 = NULL;
480         }
481       else
482         {
483           char *ptr;
484           pgm = buf + 2;
485           pgm += strspn (pgm, " \t");
486           for (ptr = pgm, arg1 = NULL;
487                *ptr && *ptr != '\r' && *ptr != '\n';
488                ptr++)
489             if (!arg1 && (*ptr == ' ' || *ptr == '\t'))
490               {
491                 /* Null terminate the initial command and step over
492                    any additional white space.  If we've hit the
493                    end of the line, exit the loop.  Otherwise, we've
494                    found the first argument. Position the current
495                    pointer on the last known white space. */
496                 *ptr = '\0';
497                 char *newptr = ptr + 1;
498                 newptr += strspn (newptr, " \t");
499                 if (!*newptr || *newptr == '\r' || *newptr == '\n')
500                   break;
501                 arg1 = newptr;
502                 ptr = newptr - 1;
503               }
504
505           *ptr = '\0';
506         }
507
508       /* Replace argv[0] with the full path to the script if this is the
509          first time through the loop. */
510       newargv.replace0_maybe (prog_arg);
511
512       /* pointers:
513        * pgm    interpreter name
514        * arg1   optional string
515        */
516       if (arg1)
517         newargv.unshift (arg1);
518
519       /* FIXME: This should not be using FE_NATIVE.  It should be putting
520          the posix path on the argv list. */
521       find_exec (pgm, real_path, "PATH=", FE_NATIVE, &ext);
522       newargv.unshift (real_path, 1);
523     }
524
525   if (real_path.iscygexec ())
526     newargv.dup_all ();
527   else
528     {
529       for (int i = 0; i < newargv.argc; i++)
530         {
531           char *p = NULL;
532           const char *a;
533
534           newargv.dup_maybe (i);
535           a = i ? newargv[i] : (char *) real_path;
536           int len = strlen (a);
537           if (len != 0 && !strpbrk (a, " \t\n\r\""))
538             one_line.add (a, len);
539           else
540             {
541               one_line.add ("\"", 1);
542               /* Handle embedded special characters " and \.
543                  A " is always preceded by a \.
544                  A \ is not special unless it precedes a ".  If it does,
545                  then all preceding \'s must be doubled to avoid having
546                  the Windows command line parser interpret the \ as quoting
547                  the ".  This rule applies to a string of \'s before the end
548                  of the string, since cygwin/windows uses a " to delimit the
549                  argument. */
550               for (; (p = strpbrk (a, "\"\\")); a = ++p)
551                 {
552                   one_line.add (a, p - a);
553                   /* Find length of string of backslashes */
554                   int n = strspn (p, "\\");
555                   if (!n)
556                     one_line.add ("\\\"", 2);   /* No backslashes, so it must be a ".
557                                                    The " has to be protected with a backslash. */
558                   else
559                     {
560                       one_line.add (p, n);      /* Add the run of backslashes */
561                       /* Need to double up all of the preceding
562                          backslashes if they precede a quote or EOS. */
563                       if (!p[n] || p[n] == '"')
564                         one_line.add (p, n);
565                       p += n - 1;               /* Point to last backslash */
566                     }
567                 }
568               if (*a)
569                 one_line.add (a);
570               one_line.add ("\"", 1);
571             }
572           MALLOC_CHECK;
573           one_line.add (" ", 1);
574           MALLOC_CHECK;
575         }
576
577       MALLOC_CHECK;
578       if (one_line.ix)
579         one_line.buf[one_line.ix - 1] = '\0';
580       else
581         one_line.add ("", 1);
582       MALLOC_CHECK;
583
584       if (one_line.ix > 32767)
585         {
586           debug_printf ("Command line too long (>32K), return E2BIG");
587           set_errno (E2BIG);
588           return -1;
589         }
590     }
591
592   char *envblock;
593   newargv.all_calloced ();
594   if (newargv.error)
595     {
596       set_errno (newargv.error);
597       return -1;
598     }
599
600   ciresrv.moreinfo->argc = newargv.argc;
601   ciresrv.moreinfo->argv = newargv;
602   ciresrv.hexec_proc = hexec_proc;
603
604   if (mode != _P_OVERLAY ||
605       !DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
606                         &ciresrv.moreinfo->myself_pinfo, 0,
607                         TRUE, DUPLICATE_SAME_ACCESS))
608     ciresrv.moreinfo->myself_pinfo = NULL;
609   else
610     VerifyHandle (ciresrv.moreinfo->myself_pinfo);
611
612  skip_arg_parsing:
613   PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
614   si.lpReserved = NULL;
615   si.lpDesktop = NULL;
616   si.dwFlags = STARTF_USESTDHANDLES;
617   si.hStdInput = handle (0, 0); /* Get input handle */
618   si.hStdOutput = handle (1, 1); /* Get output handle */
619   si.hStdError = handle (2, 1); /* Get output handle */
620   si.cb = sizeof (si);
621
622   int flags = CREATE_DEFAULT_ERROR_MODE | GetPriorityClass (hMainProc);
623
624   if (mode == _P_DETACH || !set_console_state_for_spawn ())
625     flags |= DETACHED_PROCESS;
626   if (mode != _P_OVERLAY)
627     flags |= CREATE_SUSPENDED;
628
629   /* Some file types (currently only sockets) need extra effort in the
630      parent after CreateProcess and before copying the datastructures
631      to the child. So we have to start the child in suspend state,
632      unfortunately, to avoid a race condition. */
633   if (cygheap->fdtab.need_fixup_before ())
634     flags |= CREATE_SUSPENDED;
635
636
637   const char *runpath = null_app_name ? NULL : (const char *) real_path;
638
639   syscall_printf ("null_app_name %d (%s, %.9500s)", null_app_name, runpath, one_line.buf);
640
641   void *newheap;
642
643   cygbench ("spawn-guts");
644
645   cygheap->fdtab.set_file_pointers_for_exec ();
646   cygheap->user.deimpersonate ();
647   /* When ruid != euid we create the new process under the current original
648      account and impersonate in child, this way maintaining the different
649      effective vs. real ids.
650      FIXME: If ruid != euid and ruid != saved_uid we currently give
651      up on ruid. The new process will have ruid == euid. */
652   if (!cygheap->user.issetuid ()
653       || (cygheap->user.saved_uid == cygheap->user.real_uid
654           && cygheap->user.saved_gid == cygheap->user.real_gid
655           && !cygheap->user.groups.issetgroups ()))
656     {
657       ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
658                                           real_path.iscygexec ());
659       newheap = cygheap_setup_for_child (&ciresrv, cygheap->fdtab.need_fixup_before ());
660       rc = CreateProcess (runpath,      /* image name - with full path */
661                           one_line.buf, /* what was passed to exec */
662                           &sec_none_nih,/* process security attrs */
663                           &sec_none_nih,/* thread security attrs */
664                           TRUE,         /* inherit handles from parent */
665                           flags,
666                           envblock,     /* environment */
667                           0,            /* use current drive/directory */
668                           &si,
669                           &pi);
670     }
671   else
672     {
673       /* Give access to myself */
674       if (mode == _P_OVERLAY)
675         myself.set_acl();
676
677       /* allow the child to interact with our window station/desktop */
678       HANDLE hwst, hdsk;
679       SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
680       DWORD n;
681       char wstname[1024];
682       char dskname[1024];
683
684       hwst = GetProcessWindowStation ();
685       SetUserObjectSecurity (hwst, &dsi, get_null_sd ());
686       GetUserObjectInformation (hwst, UOI_NAME, wstname, 1024, &n);
687       hdsk = GetThreadDesktop (GetCurrentThreadId ());
688       SetUserObjectSecurity (hdsk, &dsi, get_null_sd ());
689       GetUserObjectInformation (hdsk, UOI_NAME, dskname, 1024, &n);
690       strcat (wstname, "\\");
691       strcat (wstname, dskname);
692       si.lpDesktop = wstname;
693
694       ciresrv.moreinfo->envp = build_env (envp, envblock, ciresrv.moreinfo->envc,
695                                           real_path.iscygexec ());
696       newheap = cygheap_setup_for_child (&ciresrv, cygheap->fdtab.need_fixup_before ());
697       rc = CreateProcessAsUser (cygheap->user.token (),
698                        runpath,         /* image name - with full path */
699                        one_line.buf,    /* what was passed to exec */
700                        &sec_none_nih,   /* process security attrs */
701                        &sec_none_nih,   /* thread security attrs */
702                        TRUE,            /* inherit handles from parent */
703                        flags,
704                        envblock,        /* environment */
705                        0,               /* use current drive/directory */
706                        &si,
707                        &pi);
708     }
709
710   /* Restore impersonation. In case of _P_OVERLAY this isn't
711      allowed since it would overwrite child data. */
712   if (mode != _P_OVERLAY || !rc)
713       cygheap->user.reimpersonate ();
714
715   MALLOC_CHECK;
716   if (envblock)
717     free (envblock);
718   MALLOC_CHECK;
719
720   /* Set errno now so that debugging messages from it appear before our
721      final debugging message [this is a general rule for debugging
722      messages].  */
723   if (!rc)
724     {
725       __seterrno ();
726       syscall_printf ("CreateProcess failed, %E");
727       if (subproc_ready)
728         ForceCloseHandle (subproc_ready);
729       cygheap_setup_for_child_cleanup (newheap, &ciresrv, 0);
730       return -1;
731     }
732
733   /* FIXME: There is a small race here */
734
735   int res;
736   pthread_cleanup cleanup;
737   pthread_cleanup_push (do_cleanup, (void *) &cleanup);
738   if (mode == _P_SYSTEM)
739     {
740       sigset_t child_block;
741       cleanup.oldint = signal (SIGINT, SIG_IGN);
742       cleanup.oldquit = signal (SIGQUIT, SIG_IGN);
743       sigemptyset (&child_block);
744       sigaddset (&child_block, SIGCHLD);
745       (void) sigprocmask (SIG_BLOCK, &child_block, &cleanup.oldmask);
746     }
747
748   /* Fixup the parent datastructure if needed and resume the child's
749      main thread. */
750   if (!cygheap->fdtab.need_fixup_before ())
751     cygheap_setup_for_child_cleanup (newheap, &ciresrv, 0);
752   else
753     {
754       cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
755       cygheap_setup_for_child_cleanup (newheap, &ciresrv, 1);
756       if (mode == _P_OVERLAY)
757         {
758           ResumeThread (pi.hThread);
759           cygthread::terminate ();
760         }
761     }
762
763   if (mode != _P_OVERLAY)
764     cygpid = cygwin_pid (pi.dwProcessId);
765   else
766     cygpid = myself->pid;
767
768   /* We print the original program name here so the user can see that too.  */
769   syscall_printf ("%d = spawn_guts (%s, %.9500s)",
770                   rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf);
771
772   /* Name the handle similarly to proc_subproc. */
773   ProtectHandle1 (pi.hProcess, childhProc);
774
775   if (mode == _P_OVERLAY)
776     {
777       /* These are both duplicated in the child code.  We do this here,
778          primarily for strace. */
779       strace.execing = 1;
780       hExeced = pi.hProcess;
781       dwExeced = pi.dwProcessId;
782       strcpy (myself->progname, real_path);
783       close_all_files ();
784     }
785   else
786     {
787       myself->set_has_pgid_children ();
788       ProtectHandle (pi.hThread);
789       pinfo child (cygpid, PID_IN_USE);
790       if (!child)
791         {
792           syscall_printf ("pinfo failed");
793           if (get_errno () != ENOMEM)
794             set_errno (EAGAIN);
795           res = -1;
796           goto out;
797         }
798       child->dwProcessId = pi.dwProcessId;
799       child->hProcess = pi.hProcess;
800       if (!child.remember ())
801         {
802           syscall_printf ("process table full");
803           set_errno (EAGAIN);
804           res = -1;
805           goto out;
806         }
807
808       strcpy (child->progname, real_path);
809       /* FIXME: This introduces an unreferenced, open handle into the child.
810          The purpose is to keep the pid shared memory open so that all of
811          the fields filled out by child.remember do not disappear and so there
812          is not a brief period during which the pid is not available.
813          However, we should try to find another way to do this eventually. */
814       (void) DuplicateHandle (hMainProc, child.shared_handle (), pi.hProcess,
815                               NULL, 0, 0, DUPLICATE_SAME_ACCESS);
816       /* Start the child running */
817       ResumeThread (pi.hThread);
818     }
819
820   ForceCloseHandle (pi.hThread);
821
822   sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
823
824   bool exited;
825
826   res = 0;
827   exited = false;
828   MALLOC_CHECK;
829   if (mode == _P_OVERLAY)
830     {
831       int nwait = 3;
832       HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, subproc_ready};
833       for (int i = 0; i < 100; i++)
834         {
835           switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, INFINITE))
836             {
837             case WAIT_OBJECT_0:
838               sigproc_printf ("subprocess exited");
839               DWORD exitcode;
840               if (!GetExitCodeProcess (pi.hProcess, &exitcode))
841                 exitcode = 1;
842               res |= exitcode;
843               exited = true;
844               break;
845             case WAIT_OBJECT_0 + 1:
846               sigproc_printf ("signal arrived");
847               reset_signal_arrived ();
848               continue;
849             case WAIT_OBJECT_0 + 2:
850               if (my_parent_is_alive ())
851                 res |= EXIT_REPARENTING;
852               else if (!myself->ppid_handle)
853                 {
854                   nwait = 2;
855                   sigproc_terminate ();
856                   continue;
857                 }
858               break;
859             case WAIT_FAILED:
860               system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
861                              nwait, myself->pid, myself->dwProcessId);
862               system_printf ("waitbuf[0] %p %d", waitbuf[0],
863                              WaitForSingleObject (waitbuf[0], 0));
864               system_printf ("waitbuf[1] %p = %d", waitbuf[1],
865                              WaitForSingleObject (waitbuf[1], 0));
866               system_printf ("waitbuf[w] %p = %d", waitbuf[2],
867                              WaitForSingleObject (waitbuf[2], 0));
868               set_errno (ECHILD);
869               try_to_debug ();
870               return -1;
871             }
872           break;
873         }
874
875       ForceCloseHandle (subproc_ready);
876
877       sigproc_printf ("res = %x", res);
878
879       if (res & EXIT_REPARENTING)
880         {
881           /* Try to reparent child process.
882            * Make handles to child available to parent process and exit with
883            * EXIT_REPARENTING status. Wait() syscall in parent will then wait
884            * for newly created child.
885            */
886           HANDLE oldh = myself->hProcess;
887           HANDLE h = myself->ppid_handle;
888           sigproc_printf ("parent handle %p", h);
889           int rc = DuplicateHandle (hMainProc, pi.hProcess, h, &myself->hProcess,
890                                     0, FALSE, DUPLICATE_SAME_ACCESS);
891           sigproc_printf ("%d = DuplicateHandle, oldh %p, newh %p",
892                           rc, oldh, myself->hProcess);
893           VerifyHandle (myself->hProcess);
894           if (!rc && my_parent_is_alive ())
895             {
896               system_printf ("Reparent failed, parent handle %p, %E", h);
897               system_printf ("my dwProcessId %d, myself->dwProcessId %d",
898                              GetCurrentProcessId (), myself->dwProcessId);
899               system_printf ("old hProcess %p, hProcess %p", oldh, myself->hProcess);
900             }
901         }
902
903     }
904
905   MALLOC_CHECK;
906
907   switch (mode)
908     {
909     case _P_OVERLAY:
910       ForceCloseHandle1 (pi.hProcess, childhProc);
911       proc_terminate ();
912       myself->exit (res, 1);
913       break;
914     case _P_WAIT:
915     case _P_SYSTEM:
916       waitpid (cygpid, (int *) &res, 0);
917       break;
918     case _P_DETACH:
919       res = 0;  /* Lose all memory of this child. */
920       break;
921     case _P_NOWAIT:
922     case _P_NOWAITO:
923     case _P_VFORK:
924       res = cygpid;
925       break;
926     default:
927       break;
928     }
929
930 out:
931   pthread_cleanup_pop (1);
932   return (int) res;
933 }
934
935 extern "C" int
936 cwait (int *result, int pid, int)
937 {
938   return waitpid (pid, result, 0);
939 }
940
941 /*
942  * Helper function for spawn runtime calls.
943  * Doesn't search the path.
944  */
945
946 extern "C" int
947 spawnve (int mode, const char *path, const char *const *argv,
948          const char *const *envp)
949 {
950   int ret;
951 #ifdef NEWVFORK
952   vfork_save *vf = vfork_storage.val ();
953
954   if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
955     mode = _P_NOWAIT;
956   else
957     vf = NULL;
958 #endif
959
960   syscall_printf ("spawnve (%s, %s, %x)", path, argv[0], envp);
961
962   switch (mode)
963     {
964     case _P_OVERLAY:
965       /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
966       /* Just act as an exec if _P_OVERLAY set. */
967       spawn_guts (path, argv, envp, mode);
968       /* Errno should be set by spawn_guts.  */
969       ret = -1;
970       break;
971     case _P_VFORK:
972     case _P_NOWAIT:
973     case _P_NOWAITO:
974     case _P_WAIT:
975     case _P_DETACH:
976     case _P_SYSTEM:
977       subproc_init ();
978       ret = spawn_guts (path, argv, envp, mode);
979 #ifdef NEWVFORK
980       if (vf)
981         {
982           if (ret > 0)
983             {
984               debug_printf ("longjmping due to vfork");
985               vf->restore_pid (ret);
986             }
987         }
988 #endif
989       break;
990     default:
991       set_errno (EINVAL);
992       ret = -1;
993       break;
994     }
995   return ret;
996 }
997
998 /*
999  * spawn functions as implemented in the MS runtime library.
1000  * Most of these based on (and copied from) newlib/libc/posix/execXX.c
1001  */
1002
1003 extern "C" int
1004 spawnl (int mode, const char *path, const char *arg0, ...)
1005 {
1006   int i;
1007   va_list args;
1008   const char *argv[256];
1009
1010   va_start (args, arg0);
1011   argv[0] = arg0;
1012   i = 1;
1013
1014   do
1015       argv[i] = va_arg (args, const char *);
1016   while (argv[i++] != NULL);
1017
1018   va_end (args);
1019
1020   return spawnve (mode, path, (char * const  *) argv, cur_environ ());
1021 }
1022
1023 extern "C" int
1024 spawnle (int mode, const char *path, const char *arg0, ...)
1025 {
1026   int i;
1027   va_list args;
1028   const char * const *envp;
1029   const char *argv[256];
1030
1031   va_start (args, arg0);
1032   argv[0] = arg0;
1033   i = 1;
1034
1035   do
1036     argv[i] = va_arg (args, const char *);
1037   while (argv[i++] != NULL);
1038
1039   envp = va_arg (args, const char * const *);
1040   va_end (args);
1041
1042   return spawnve (mode, path, (char * const *) argv, (char * const *) envp);
1043 }
1044
1045 extern "C" int
1046 spawnlp (int mode, const char *path, const char *arg0, ...)
1047 {
1048   int i;
1049   va_list args;
1050   const char *argv[256];
1051
1052   va_start (args, arg0);
1053   argv[0] = arg0;
1054   i = 1;
1055
1056   do
1057       argv[i] = va_arg (args, const char *);
1058   while (argv[i++] != NULL);
1059
1060   va_end (args);
1061
1062   return spawnvpe (mode, path, (char * const *) argv, cur_environ ());
1063 }
1064
1065 extern "C" int
1066 spawnlpe (int mode, const char *path, const char *arg0, ...)
1067 {
1068   int i;
1069   va_list args;
1070   const char * const *envp;
1071   const char *argv[256];
1072
1073   va_start (args, arg0);
1074   argv[0] = arg0;
1075   i = 1;
1076
1077   do
1078     argv[i] = va_arg (args, const char *);
1079   while (argv[i++] != NULL);
1080
1081   envp = va_arg (args, const char * const *);
1082   va_end (args);
1083
1084   return spawnvpe (mode, path, (char * const *) argv, envp);
1085 }
1086
1087 extern "C" int
1088 spawnv (int mode, const char *path, const char * const *argv)
1089 {
1090   return spawnve (mode, path, argv, cur_environ ());
1091 }
1092
1093 extern "C" int
1094 spawnvp (int mode, const char *path, const char * const *argv)
1095 {
1096   return spawnvpe (mode, path, argv, cur_environ ());
1097 }
1098
1099 extern "C" int
1100 spawnvpe (int mode, const char *file, const char * const *argv,
1101                                              const char * const *envp)
1102 {
1103   path_conv buf;
1104   return spawnve (mode, find_exec (file, buf), argv, envp);
1105 }