OSDN Git Service

gas/opcodes: blackfin: move dsp mac func defines to common header
[pf3gnuchains/sourceware.git] / winsup / cygwin / spawn.cc
1 /* spawn.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4    2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <process.h>
16 #include <sys/wait.h>
17 #include <wingdi.h>
18 #include <winuser.h>
19 #include <wchar.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 "pinfo.h"
31 #include "environ.h"
32 #include "cygtls.h"
33 #include "tls_pbuf.h"
34 #include "winf.h"
35 #include "ntdll.h"
36
37 static suffix_info exe_suffixes[] =
38 {
39   suffix_info ("", 1),
40   suffix_info (".exe", 1),
41   suffix_info (".com"),
42   suffix_info (NULL)
43 };
44
45 #if 0
46 /* CV, 2009-11-05: Used to be used when searching for DLLs in calls to
47    dlopen().  However, dlopen() on other platforms never adds a suffix by
48    its own.  Therefore we use stat_suffixes now, which only adds a .exe
49    suffix for symmetry. */
50 static suffix_info dll_suffixes[] =
51 {
52   suffix_info (".dll"),
53   suffix_info ("", 1),
54   suffix_info (".exe", 1),
55   suffix_info (NULL)
56 };
57 #endif
58
59 child_info_spawn *chExeced;
60
61 /* Add .exe to PROG if not already present and see if that exists.
62    If not, return PROG (converted from posix to win32 rules if necessary).
63    The result is always BUF.
64
65    Returns (possibly NULL) suffix */
66
67 static const char *
68 perhaps_suffix (const char *prog, path_conv& buf, int& err, unsigned opt)
69 {
70   const char *ext;
71
72   err = 0;
73   debug_printf ("prog '%s'", prog);
74   buf.check (prog, PC_SYM_FOLLOW | PC_NULLEMPTY,
75              (opt & FE_DLL) ? stat_suffixes : exe_suffixes);
76
77   if (buf.isdir ())
78     {
79       err = EACCES;
80       ext = NULL;
81     }
82   else if (!buf.exists ())
83     {
84       err = ENOENT;
85       ext = NULL;
86     }
87   else if (buf.known_suffix)
88     ext = buf.get_win32 () + (buf.known_suffix - buf.get_win32 ());
89   else
90     ext = strchr (buf.get_win32 (), '\0');
91
92   debug_printf ("buf %s, suffix found '%s'", (char *) buf.get_win32 (), ext);
93   return ext;
94 }
95
96 /* Find an executable name, possibly by appending known executable
97    suffixes to it.  The win32-translated name is placed in 'buf'.
98    Any found suffix is returned in known_suffix.
99
100    If the file is not found and !null_if_not_found then the win32 version
101    of name is placed in buf and returned.  Otherwise the contents of buf
102    is undefined and NULL is returned.  */
103
104 const char * __stdcall
105 find_exec (const char *name, path_conv& buf, const char *mywinenv,
106            unsigned opt, const char **known_suffix)
107 {
108   const char *suffix = "";
109   debug_printf ("find_exec (%s)", name);
110   const char *retval;
111   tmp_pathbuf tp;
112   char *tmp = tp.c_get ();
113   const char *posix = (opt & FE_NATIVE) ? NULL : name;
114   bool has_slash = !!strpbrk (name, "/\\");
115   int err;
116
117   /* Check to see if file can be opened as is first.
118      Win32 systems always check . first, but PATH may not be set up to
119      do this. */
120   if ((has_slash || opt & FE_CWD)
121       && (suffix = perhaps_suffix (name, buf, err, opt)) != NULL)
122     {
123       if (posix && !has_slash)
124         {
125           tmp[0] = '.';
126           tmp[1] = '/';
127           strcpy (tmp + 2, name);
128           posix = tmp;
129         }
130       retval = buf.get_win32 ();
131       goto out;
132     }
133
134   win_env *winpath;
135   const char *path;
136   const char *posix_path;
137
138   posix = (opt & FE_NATIVE) ? NULL : tmp;
139
140   if (strchr (mywinenv, '/'))
141     {
142       /* it's not really an environment variable at all */
143       int n = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, mywinenv, NULL, 0);
144       char *s = (char *) alloca (n);
145       if (cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, mywinenv, s, n))
146         goto errout;
147       path = s;
148       posix_path = mywinenv - 1;
149     }
150   else if (has_slash || strchr (name, '\\') || isdrive (name)
151       || !(winpath = getwinenv (mywinenv))
152       || !(path = winpath->get_native ()) || *path == '\0')
153     /* Return the error condition if this is an absolute path or if there
154        is no PATH to search. */
155     goto errout;
156   else
157     posix_path = winpath->get_posix () - 1;
158
159   debug_printf ("%s%s", mywinenv, path);
160   /* Iterate over the specified path, looking for the file with and without
161      executable extensions. */
162   do
163     {
164       posix_path++;
165       char *eotmp = strccpy (tmp, &path, ';');
166       /* An empty path or '.' means the current directory, but we've
167          already tried that.  */
168       if (opt & FE_CWD && (tmp[0] == '\0' || (tmp[0] == '.' && tmp[1] == '\0')))
169         continue;
170
171       *eotmp++ = '\\';
172       strcpy (eotmp, name);
173
174       debug_printf ("trying %s", tmp);
175
176       int err1;
177
178       if ((suffix = perhaps_suffix (tmp, buf, err1, opt)) != NULL)
179         {
180           if (buf.has_acls () && check_file_access (buf, X_OK, true))
181             continue;
182
183           if (posix == tmp)
184             {
185               eotmp = strccpy (tmp, &posix_path, ':');
186               if (eotmp == tmp)
187                 *eotmp++ = '.';
188               *eotmp++ = '/';
189               strcpy (eotmp, name);
190             }
191           retval = buf.get_win32 ();
192           goto out;
193         }
194     }
195   while (*path && *++path && (posix_path = strchr (posix_path, ':')));
196
197  errout:
198   posix = NULL;
199   /* Couldn't find anything in the given path.
200      Take the appropriate action based on null_if_not_found. */
201   if (opt & FE_NNF)
202     retval = NULL;
203   else if (!(opt & FE_NATIVE))
204     retval = name;
205   else
206     {
207       buf.check (name);
208       retval = buf.get_win32 ();
209     }
210
211  out:
212   if (posix)
213     retval = buf.set_path (posix);
214   debug_printf ("%s = find_exec (%s)", (char *) buf.get_win32 (), name);
215   if (known_suffix)
216     *known_suffix = suffix ?: strchr (buf.get_win32 (), '\0');
217   if (!retval && err)
218     set_errno (err);
219   return retval;
220 }
221
222 /* Utility for spawn_guts.  */
223
224 static HANDLE
225 handle (int fd, bool writing)
226 {
227   HANDLE h;
228   cygheap_fdget cfd (fd);
229
230   if (cfd < 0)
231     h = INVALID_HANDLE_VALUE;
232   else if (cfd->close_on_exec ())
233     h = INVALID_HANDLE_VALUE;
234   else if (!writing)
235     h = cfd->get_handle ();
236   else
237     h = cfd->get_output_handle ();
238
239   return h;
240 }
241
242 int
243 iscmd (const char *argv0, const char *what)
244 {
245   int n;
246   n = strlen (argv0) - strlen (what);
247   if (n >= 2 && argv0[1] != ':')
248     return 0;
249   return n >= 0 && strcasematch (argv0 + n, what) &&
250          (n == 0 || isdirsep (argv0[n - 1]));
251 }
252
253 struct pthread_cleanup
254 {
255   _sig_func_ptr oldint;
256   _sig_func_ptr oldquit;
257   sigset_t oldmask;
258   pthread_cleanup (): oldint (NULL), oldquit (NULL), oldmask ((sigset_t) -1) {}
259 };
260
261 static void
262 do_cleanup (void *args)
263 {
264 # define cleanup ((pthread_cleanup *) args)
265   if (cleanup->oldmask != (sigset_t) -1)
266     {
267       signal (SIGINT, cleanup->oldint);
268       signal (SIGQUIT, cleanup->oldquit);
269       sigprocmask (SIG_SETMASK, &(cleanup->oldmask), NULL);
270     }
271 # undef cleanup
272 }
273
274
275 int
276 spawn_guts (const char *prog_arg, const char *const *argv,
277             const char *const envp[], int mode, int __stdin, int __stdout)
278 {
279   bool rc;
280   pid_t cygpid;
281   int res = -1;
282
283   /* Check if we have been called from exec{lv}p or spawn{lv}p and mask
284      mode to keep only the spawn mode. */
285   bool p_type_exec = !!(mode & _P_PATH_TYPE_EXEC);
286   mode = _P_MODE (mode);
287
288   if (prog_arg == NULL)
289     {
290       syscall_printf ("prog_arg is NULL");
291       set_errno (EFAULT);       /* As on Linux. */
292       return -1;
293     }
294   if (!prog_arg[0])
295     {
296       syscall_printf ("prog_arg is empty");
297       set_errno (ENOENT);       /* Per POSIX */
298       return -1;
299     }
300
301   syscall_printf ("spawn_guts (%d, %.9500s)", mode, prog_arg);
302
303   /* FIXME: This is no error condition on Linux. */
304   if (argv == NULL)
305     {
306       syscall_printf ("argv is NULL");
307       set_errno (EINVAL);
308       return -1;
309     }
310
311   /* FIXME: There is a small race here and FIXME: not thread safe! */
312
313   pthread_cleanup cleanup;
314   if (mode == _P_SYSTEM)
315     {
316       sigset_t child_block;
317       cleanup.oldint = signal (SIGINT, SIG_IGN);
318       cleanup.oldquit = signal (SIGQUIT, SIG_IGN);
319       sigemptyset (&child_block);
320       sigaddset (&child_block, SIGCHLD);
321       sigprocmask (SIG_BLOCK, &child_block, &cleanup.oldmask);
322     }
323   pthread_cleanup_push (do_cleanup, (void *) &cleanup);
324   av newargv;
325   linebuf one_line;
326   child_info_spawn ch;
327   PWCHAR envblock = NULL;
328   path_conv real_path;
329   bool reset_sendsig = false;
330
331   tmp_pathbuf tp;
332   PWCHAR runpath = tp.w_get ();
333   int c_flags;
334   bool wascygexec;
335   cygheap_exec_info *moreinfo;
336
337   bool null_app_name = false;
338   STARTUPINFOW si = {};
339   int looped = 0;
340   HANDLE orig_wr_proc_pipe = NULL;
341
342   myfault efault;
343   if (efault.faulted ())
344     {
345       if (get_errno () == ENOMEM)
346         set_errno (E2BIG);
347       else
348         set_errno (EFAULT);
349       res = -1;
350       goto out;
351     }
352
353   child_info_types chtype;
354   if (mode != _P_OVERLAY)
355     chtype = PROC_SPAWN;
356   else
357     chtype = PROC_EXEC;
358
359   moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
360                                                   sizeof (cygheap_exec_info));
361   moreinfo->old_title = NULL;
362
363   /* CreateProcess takes one long string that is the command line (sigh).
364      We need to quote any argument that has whitespace or embedded "'s.  */
365
366   int ac;
367   for (ac = 0; argv[ac]; ac++)
368     /* nothing */;
369
370   newargv.set (ac, argv);
371
372   int err;
373   const char *ext;
374   if ((ext = perhaps_suffix (prog_arg, real_path, err, FE_NADA)) == NULL)
375     {
376       set_errno (err);
377       res = -1;
378       goto out;
379     }
380
381
382   wascygexec = real_path.iscygexec ();
383   res = newargv.fixup (prog_arg, real_path, ext, p_type_exec);
384
385   if (res)
386     goto out;
387
388   if (!real_path.iscygexec () && cygheap->cwd.get_error ())
389     {
390       small_printf ("Error: Current working directory %s.\n"
391                     "Can't start native Windows application from here.\n\n",
392                     cygheap->cwd.get_error_desc ());
393       set_errno (cygheap->cwd.get_error ());
394       res = -1;
395       goto out;
396     }
397
398   if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
399       (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
400     {
401       real_path.check (prog_arg);
402       one_line.add ("\"");
403       if (!real_path.error)
404         one_line.add (real_path.get_win32 ());
405       else
406         one_line.add (argv[0]);
407       one_line.add ("\"");
408       one_line.add (" ");
409       one_line.add (argv[1]);
410       one_line.add (" ");
411       one_line.add (argv[2]);
412       real_path.set_path (argv[0]);
413       null_app_name = true;
414     }
415   else
416     {
417       if (wascygexec)
418         newargv.dup_all ();
419       else if (!one_line.fromargv (newargv, real_path.get_win32 (),
420                                    real_path.iscygexec ()))
421         {
422           res = -1;
423           goto out;
424         }
425
426
427       newargv.all_calloced ();
428       moreinfo->argc = newargv.argc;
429       moreinfo->argv = newargv;
430
431       if (mode != _P_OVERLAY ||
432           !DuplicateHandle (GetCurrentProcess (), myself.shared_handle (),
433                             GetCurrentProcess (), &moreinfo->myself_pinfo,
434                             0, TRUE, DUPLICATE_SAME_ACCESS))
435         moreinfo->myself_pinfo = NULL;
436       else
437         VerifyHandle (moreinfo->myself_pinfo);
438     }
439   WCHAR wone_line[one_line.ix + 1];
440   if (one_line.ix)
441     sys_mbstowcs (wone_line, one_line.ix + 1, one_line.buf);
442   else
443     wone_line[0] = L'\0';
444
445   PROCESS_INFORMATION pi;
446   pi.hProcess = pi.hThread = NULL;
447   pi.dwProcessId = pi.dwThreadId = 0;
448
449   /* Set up needed handles for stdio */
450   si.dwFlags = STARTF_USESTDHANDLES;
451   si.hStdInput = handle ((__stdin < 0 ? 0 : __stdin), false);
452   si.hStdOutput = handle ((__stdout < 0 ? 1 : __stdout), true);
453   si.hStdError = handle (2, true);
454
455   si.cb = sizeof (si);
456
457   c_flags = GetPriorityClass (GetCurrentProcess ());
458   sigproc_printf ("priority class %d", c_flags);
459   c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT;
460
461   if (mode == _P_DETACH)
462     c_flags |= DETACHED_PROCESS;
463   else
464     fhandler_console::need_invisible ();
465
466   if (mode != _P_OVERLAY)
467     myself->exec_sendsig = NULL;
468   else
469     {
470       /* Reset sendsig so that any process which wants to send a signal
471          to this pid will wait for the new process to become active.
472          Save the old value in case the exec fails.  */
473       if (!myself->exec_sendsig)
474         {
475           myself->exec_sendsig = myself->sendsig;
476           myself->exec_dwProcessId = myself->dwProcessId;
477           myself->sendsig = NULL;
478           reset_sendsig = true;
479         }
480       /* Save a copy of a handle to the current process around the first time we
481          exec so that the pid will not be reused.  Why did I stop cygwin from
482          generating its own pids again? */
483       if (cygheap->pid_handle)
484         /* already done previously */;
485       else if (DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
486                                 GetCurrentProcess (), &cygheap->pid_handle,
487                                 PROCESS_QUERY_INFORMATION, TRUE, 0))
488         ProtectHandleINH (cygheap->pid_handle);
489       else
490         system_printf ("duplicate to pid_handle failed, %E");
491     }
492
493   runpath = null_app_name ? NULL : real_path.get_wide_win32_path (runpath);
494   if (runpath)
495     { /* If the executable path length is < MAX_PATH, make sure the long path
496          win32 prefix is removed from the path to make subsequent native Win32
497          child processes happy which are not long path aware. */
498       USHORT len = real_path.get_nt_native_path ()->Length;
499       if (len < (MAX_PATH + 4) * sizeof (WCHAR)
500           || (runpath[5] != L':'                                /* UNC path */
501               && len < (MAX_PATH + 6) * sizeof (WCHAR)))
502         {
503           PWCHAR r = runpath + 4;
504           if (r[1] != L':') /* UNC path */
505             *(r += 2) = L'\\';
506           if (!RtlIsDosDeviceName_U (r))
507             runpath = r;
508           else if (*r == L'\\')
509             *r = L'C';
510         }
511     }
512
513   syscall_printf ("null_app_name %d (%W, %.9500W)", null_app_name,
514                   runpath, wone_line);
515
516   cygbench ("spawn-guts");
517
518   if (!real_path.iscygexec())
519     cygheap->fdtab.set_file_pointers_for_exec ();
520
521   moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
522                               real_path.iscygexec ());
523   if (!moreinfo->envp || !envblock)
524     {
525       set_errno (E2BIG);
526       res = -1;
527       goto out;
528     }
529   ch.set (chtype, real_path.iscygexec ());
530   ch.moreinfo = moreinfo;
531   ch.__stdin = __stdin;
532   ch.__stdout = __stdout;
533
534   si.lpReserved2 = (LPBYTE) &ch;
535   si.cbReserved2 = sizeof (ch);
536
537   /* Depends on ch.set call above.
538      Some file types might need extra effort in the parent after CreateProcess
539      and before copying the datastructures to the child.  So we have to start
540      the child in suspend state, unfortunately, to avoid a race condition. */
541   if (!newargv.win16_exe
542       && (!ch.iscygwin () || mode != _P_OVERLAY
543           || cygheap->fdtab.need_fixup_before ()))
544     c_flags |= CREATE_SUSPENDED;
545
546   /* When ruid != euid we create the new process under the current original
547      account and impersonate in child, this way maintaining the different
548      effective vs. real ids.
549      FIXME: If ruid != euid and ruid != saved_uid we currently give
550      up on ruid. The new process will have ruid == euid. */
551 loop:
552   cygheap->user.deimpersonate ();
553
554   PWCHAR cwd;
555   cwd = NULL;
556   if (!real_path.iscygexec ())
557     {
558       myself->process_state |= PID_NOTCYGWIN;
559       cygheap->cwd.cwd_lock.acquire ();
560       cwd = cygheap->cwd.win32.Buffer;
561     }
562
563   if (!cygheap->user.issetuid ()
564       || (cygheap->user.saved_uid == cygheap->user.real_uid
565           && cygheap->user.saved_gid == cygheap->user.real_gid
566           && !cygheap->user.groups.issetgroups ()
567           && !cygheap->user.setuid_to_restricted))
568     {
569       rc = CreateProcessW (runpath,       /* image name - with full path */
570                            wone_line,     /* what was passed to exec */
571                            &sec_none_nih, /* process security attrs */
572                            &sec_none_nih, /* thread security attrs */
573                            TRUE,          /* inherit handles from parent */
574                            c_flags,
575                            envblock,      /* environment */
576                            cwd,
577                            &si,
578                            &pi);
579     }
580   else
581     {
582       /* Give access to myself */
583       if (mode == _P_OVERLAY)
584         myself.set_acl();
585
586       WCHAR wstname[1024] = { L'\0' };
587       HWINSTA hwst_orig = NULL, hwst = NULL;
588       HDESK hdsk_orig = NULL, hdsk = NULL;
589       PSECURITY_ATTRIBUTES sa;
590       DWORD n;
591
592       hwst_orig = GetProcessWindowStation ();
593       hdsk_orig = GetThreadDesktop (GetCurrentThreadId ());
594       GetUserObjectInformationW (hwst_orig, UOI_NAME, wstname, 1024, &n);
595       /* Prior to Vista it was possible to start a service with the
596          "Interact with desktop" flag.  This started the service in the
597          interactive window station of the console.  A big security
598          risk, but we don't want to disable this behaviour for older
599          OSes because it's still heavily used by some users.  They have
600          been warned. */
601       if (!cygheap->user.setuid_to_restricted
602           && wcscasecmp (wstname, L"WinSta0") != 0)
603         {
604           WCHAR sid[128];
605
606           sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
607                          cygheap->user.sid ());
608           /* We're creating a window station per user, not per logon session.
609              First of all we might not have a valid logon session for
610              the user (logon by create_token), and second, it doesn't
611              make sense in terms of security to create a new window
612              station for every logon of the same user.  It just fills up
613              the system with window stations for no good reason. */
614           hwst = CreateWindowStationW (cygheap->user.get_windows_id (sid), 0,
615                                        GENERIC_READ | GENERIC_WRITE, sa);
616           if (!hwst)
617             system_printf ("CreateWindowStation failed, %E");
618           else if (!SetProcessWindowStation (hwst))
619             system_printf ("SetProcessWindowStation failed, %E");
620           else if (!(hdsk = CreateDesktopW (L"Default", NULL, NULL, 0,
621                                             GENERIC_ALL, sa)))
622             system_printf ("CreateDesktop failed, %E");
623           else
624             {
625               wcpcpy (wcpcpy (wstname, sid), L"\\Default");
626               si.lpDesktop = wstname;
627               debug_printf ("Desktop: %W", si.lpDesktop);
628             }
629         }
630
631       rc = CreateProcessAsUserW (cygheap->user.primary_token (),
632                            runpath,       /* image name - with full path */
633                            wone_line,     /* what was passed to exec */
634                            &sec_none_nih, /* process security attrs */
635                            &sec_none_nih, /* thread security attrs */
636                            TRUE,          /* inherit handles from parent */
637                            c_flags,
638                            envblock,      /* environment */
639                            cwd,
640                            &si,
641                            &pi);
642       if (hwst)
643         {
644           SetProcessWindowStation (hwst_orig);
645           CloseWindowStation (hwst);
646         }
647       if (hdsk)
648         {
649           SetThreadDesktop (hdsk_orig);
650           CloseDesktop (hdsk);
651         }
652     }
653
654   if (!real_path.iscygexec())
655     cygheap->cwd.cwd_lock.release ();
656     
657   /* Restore impersonation. In case of _P_OVERLAY this isn't
658      allowed since it would overwrite child data. */
659   if (mode != _P_OVERLAY || !rc)
660     cygheap->user.reimpersonate ();
661
662   /* Set errno now so that debugging messages from it appear before our
663      final debugging message [this is a general rule for debugging
664      messages].  */
665   if (!rc)
666     {
667       __seterrno ();
668       syscall_printf ("CreateProcess failed, %E");
669       /* If this was a failed exec, restore the saved sendsig. */
670       if (reset_sendsig)
671         {
672           myself->sendsig = myself->exec_sendsig;
673           myself->exec_sendsig = NULL;
674         }
675       res = -1;
676       goto out;
677     }
678
679   if (!(c_flags & CREATE_SUSPENDED))
680     strace.write_childpid (ch, pi.dwProcessId);
681
682   /* Fixup the parent data structures if needed and resume the child's
683      main thread. */
684   if (cygheap->fdtab.need_fixup_before ())
685     cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
686
687   if (mode != _P_OVERLAY)
688     cygpid = cygwin_pid (pi.dwProcessId);
689   else
690     cygpid = myself->pid;
691
692   /* We print the original program name here so the user can see that too.  */
693   syscall_printf ("%d = spawn_guts (%s, %.9500s)",
694                   rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf);
695
696   /* Name the handle similarly to proc_subproc. */
697   ProtectHandle1 (pi.hProcess, childhProc);
698
699   bool synced;
700   pid_t pid;
701   if (mode == _P_OVERLAY)
702     {
703       chExeced = &ch;   /* FIXME: there's a race here if a user sneaks in CTRL-C */
704       myself->dwProcessId = pi.dwProcessId;
705       strace.execing = 1;
706       myself.hProcess = hExeced = pi.hProcess;
707       real_path.get_wide_win32_path (myself->progname); // FIXME: race?
708       sigproc_printf ("new process name %W", myself->progname);
709       /* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
710          process.  So, we need to wait around until the process we've just "execed"
711          dies.  Use our own wait facility to wait for our own pid to exit (there
712          is some minor special case code in proc_waiter and friends to accommodate
713          this).
714
715          If wr_proc_pipe exists, then it should be duplicated to the child.
716          If the child has exited already, that's ok.  The parent will pick up
717          on this fact when we exit.  dup_proc_pipe will close our end of the pipe.
718          Note that wr_proc_pipe may also be == INVALID_HANDLE_VALUE.  That will make
719          dup_proc_pipe essentially a no-op.  */
720       if (!newargv.win16_exe && myself->wr_proc_pipe)
721         {
722           if (!looped)
723             myself->sync_proc_pipe ();  /* Make sure that we own wr_proc_pipe
724                                            just in case we've been previously
725                                            execed. */
726           orig_wr_proc_pipe = myself->dup_proc_pipe (pi.hProcess);
727         }
728       pid = myself->pid;
729       if (!ch.iscygwin ())
730         close_all_files ();
731     }
732   else
733     {
734       myself->set_has_pgid_children ();
735       ProtectHandle (pi.hThread);
736       pinfo child (cygpid,
737                    PID_IN_USE | (real_path.iscygexec () ? 0 : PID_NOTCYGWIN));
738       if (!child)
739         {
740           syscall_printf ("pinfo failed");
741           if (get_errno () != ENOMEM)
742             set_errno (EAGAIN);
743           res = -1;
744           goto out;
745         }
746       child->dwProcessId = pi.dwProcessId;
747       child.hProcess = pi.hProcess;
748
749       real_path.get_wide_win32_path (child->progname);
750       /* FIXME: This introduces an unreferenced, open handle into the child.
751          The purpose is to keep the pid shared memory open so that all of
752          the fields filled out by child.remember do not disappear and so there
753          is not a brief period during which the pid is not available.
754          However, we should try to find another way to do this eventually. */
755       DuplicateHandle (GetCurrentProcess (), child.shared_handle (),
756                        pi.hProcess, NULL, 0, 0, DUPLICATE_SAME_ACCESS);
757       child->start_time = time (NULL); /* Register child's starting time. */
758       child->nice = myself->nice;
759       if (!child.remember (mode == _P_DETACH))
760         {
761           /* FIXME: Child in strange state now */
762           CloseHandle (pi.hProcess);
763           ForceCloseHandle (pi.hThread);
764           res = -1;
765           goto out;
766         }
767       pid = child->pid;
768     }
769
770   /* Start the child running */
771   if (c_flags & CREATE_SUSPENDED)
772     {
773       ResumeThread (pi.hThread);
774       strace.write_childpid (ch, pi.dwProcessId);
775     }
776   ForceCloseHandle (pi.hThread);
777
778   sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
779
780   if ((mode == _P_DETACH || mode == _P_NOWAIT) && !ch.iscygwin ())
781     synced = false;
782   else
783     synced = ch.sync (pi.dwProcessId, pi.hProcess, INFINITE);
784
785   switch (mode)
786     {
787     case _P_OVERLAY:
788       myself.hProcess = pi.hProcess;
789       if (!synced)
790         {
791           if (orig_wr_proc_pipe)
792             {
793               myself->wr_proc_pipe_owner = GetCurrentProcessId ();
794               myself->wr_proc_pipe = orig_wr_proc_pipe;
795             }
796           if (!ch.proc_retry (pi.hProcess))
797             {
798               looped++;
799               goto loop;
800             }
801           close_all_files (true);
802         }
803       else
804         {
805           close_all_files (true);
806           if (!myself->wr_proc_pipe
807               && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
808             {
809               extern bool is_toplevel_proc;
810               is_toplevel_proc = true;
811               myself.remember (false);
812               waitpid (myself->pid, &res, 0);
813             }
814         }
815       myself.exit (EXITCODE_NOSET);
816       break;
817     case _P_WAIT:
818     case _P_SYSTEM:
819       if (waitpid (cygpid, &res, 0) != cygpid)
820         res = -1;
821       break;
822     case _P_DETACH:
823       res = 0;  /* Lost all memory of this child. */
824       break;
825     case _P_NOWAIT:
826     case _P_NOWAITO:
827     case _P_VFORK:
828       res = cygpid;
829       break;
830     default:
831       break;
832     }
833
834 out:
835   if (envblock)
836     free (envblock);
837   pthread_cleanup_pop (1);
838   return (int) res;
839 #undef ch
840 }
841
842 extern "C" int
843 cwait (int *result, int pid, int)
844 {
845   return waitpid (pid, result, 0);
846 }
847
848 /*
849 * Helper function for spawn runtime calls.
850 * Doesn't search the path.
851 */
852
853 extern "C" int
854 spawnve (int mode, const char *path, const char *const *argv,
855        const char *const *envp)
856 {
857   static char *const empty_env[] = { NULL };
858
859   int ret;
860 #ifdef NEWVFORK
861   vfork_save *vf = vfork_storage.val ();
862
863   if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
864     mode = _P_NOWAIT;
865   else
866     vf = NULL;
867 #endif
868
869   syscall_printf ("spawnve (%s, %s, %x)", path, argv[0], envp);
870
871   if (!envp)
872     envp = empty_env;
873
874   switch (_P_MODE (mode))
875     {
876     case _P_OVERLAY:
877       spawn_guts (path, argv, envp, mode);
878       /* Errno should be set by spawn_guts.  */
879       ret = -1;
880       break;
881     case _P_VFORK:
882     case _P_NOWAIT:
883     case _P_NOWAITO:
884     case _P_WAIT:
885     case _P_DETACH:
886     case _P_SYSTEM:
887       ret = spawn_guts (path, argv, envp, mode);
888 #ifdef NEWVFORK
889       if (vf)
890         {
891           if (ret > 0)
892             {
893               debug_printf ("longjmping due to vfork");
894               vf->restore_pid (ret);
895             }
896         }
897 #endif
898       break;
899     default:
900       set_errno (EINVAL);
901       ret = -1;
902       break;
903     }
904   return ret;
905 }
906
907 /*
908 * spawn functions as implemented in the MS runtime library.
909 * Most of these based on (and copied from) newlib/libc/posix/execXX.c
910 */
911
912 extern "C" int
913 spawnl (int mode, const char *path, const char *arg0, ...)
914 {
915   int i;
916   va_list args;
917   const char *argv[256];
918
919   va_start (args, arg0);
920   argv[0] = arg0;
921   i = 1;
922
923   do
924       argv[i] = va_arg (args, const char *);
925   while (argv[i++] != NULL);
926
927   va_end (args);
928
929   return spawnve (mode, path, (char * const  *) argv, cur_environ ());
930 }
931
932 extern "C" int
933 spawnle (int mode, const char *path, const char *arg0, ...)
934 {
935   int i;
936   va_list args;
937   const char * const *envp;
938   const char *argv[256];
939
940   va_start (args, arg0);
941   argv[0] = arg0;
942   i = 1;
943
944   do
945     argv[i] = va_arg (args, const char *);
946   while (argv[i++] != NULL);
947
948   envp = va_arg (args, const char * const *);
949   va_end (args);
950
951   return spawnve (mode, path, (char * const *) argv, (char * const *) envp);
952 }
953
954 extern "C" int
955 spawnlp (int mode, const char *file, const char *arg0, ...)
956 {
957   int i;
958   va_list args;
959   const char *argv[256];
960   path_conv buf;
961
962   va_start (args, arg0);
963   argv[0] = arg0;
964   i = 1;
965
966   do
967       argv[i] = va_arg (args, const char *);
968   while (argv[i++] != NULL);
969
970   va_end (args);
971
972   return spawnve (mode | _P_PATH_TYPE_EXEC, find_exec (file, buf),
973                   (char * const *) argv, cur_environ ());
974 }
975
976 extern "C" int
977 spawnlpe (int mode, const char *file, const char *arg0, ...)
978 {
979   int i;
980   va_list args;
981   const char * const *envp;
982   const char *argv[256];
983   path_conv buf;
984
985   va_start (args, arg0);
986   argv[0] = arg0;
987   i = 1;
988
989   do
990     argv[i] = va_arg (args, const char *);
991   while (argv[i++] != NULL);
992
993   envp = va_arg (args, const char * const *);
994   va_end (args);
995
996   return spawnve (mode | _P_PATH_TYPE_EXEC, find_exec (file, buf),
997                   (char * const *) argv, envp);
998 }
999
1000 extern "C" int
1001 spawnv (int mode, const char *path, const char * const *argv)
1002 {
1003   return spawnve (mode, path, argv, cur_environ ());
1004 }
1005
1006 extern "C" int
1007 spawnvp (int mode, const char *file, const char * const *argv)
1008 {
1009   path_conv buf;
1010   return spawnve (mode | _P_PATH_TYPE_EXEC, find_exec (file, buf), argv,
1011                   cur_environ ());
1012 }
1013
1014 extern "C" int
1015 spawnvpe (int mode, const char *file, const char * const *argv,
1016           const char * const *envp)
1017 {
1018   path_conv buf;
1019   return spawnve (mode | _P_PATH_TYPE_EXEC, find_exec (file, buf), argv, envp);
1020 }
1021
1022 int
1023 av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
1024            bool p_type_exec)
1025 {
1026   const char *p;
1027   bool exeext = ascii_strcasematch (ext, ".exe");
1028   if ((exeext && real_path.iscygexec ()) || ascii_strcasematch (ext, ".bat"))
1029     return 0;
1030   if (!*ext && ((p = ext - 4) > real_path.get_win32 ())
1031       && (ascii_strcasematch (p, ".bat") || ascii_strcasematch (p, ".cmd")
1032           || ascii_strcasematch (p, ".btm")))
1033     return 0;
1034   while (1)
1035     {
1036       char *pgm = NULL;
1037       char *arg1 = NULL;
1038       char *ptr, *buf;
1039       OBJECT_ATTRIBUTES attr;
1040       IO_STATUS_BLOCK io;
1041       HANDLE h;
1042       NTSTATUS status;
1043
1044       status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
1045                            real_path.get_object_attr (attr, sec_none_nih),
1046                            &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
1047                            FILE_SYNCHRONOUS_IO_NONALERT
1048                            | FILE_OPEN_FOR_BACKUP_INTENT
1049                            | FILE_NON_DIRECTORY_FILE);
1050       if (!NT_SUCCESS (status))
1051         {
1052           /* File is not readable?  Doesn't mean it's not executable.
1053              Test for executablility and if so, just assume the file is
1054              a cygwin executable and go ahead. */
1055           if (status == STATUS_ACCESS_DENIED && real_path.has_acls ()
1056               && check_file_access (real_path, X_OK, true) == 0)
1057             {
1058               real_path.set_cygexec (true);
1059               break;
1060             }
1061           goto err;
1062         }
1063
1064       HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL);
1065       NtClose (h);
1066       if (!hm)
1067         {
1068           /* ERROR_FILE_INVALID indicates very likely an empty file. */
1069           if (GetLastError () == ERROR_FILE_INVALID)
1070             {
1071               debug_printf ("zero length file, treat as script.");
1072               goto just_shell;
1073             }
1074           goto err;
1075         }
1076       buf = (char *) MapViewOfFile(hm, FILE_MAP_READ, 0, 0, 0);
1077       CloseHandle (hm);
1078       if (!buf)
1079         goto err;
1080
1081       {
1082         myfault efault;
1083         if (efault.faulted ())
1084           {
1085             UnmapViewOfFile (buf);
1086             real_path.set_cygexec (false);
1087             break;
1088           }
1089         if (buf[0] == 'M' && buf[1] == 'Z')
1090           {
1091             WORD subsys;
1092             unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
1093             win16_exe = off < sizeof (IMAGE_DOS_HEADER);
1094             if (!win16_exe)
1095               real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL, subsys));
1096             else
1097               real_path.set_cygexec (false);
1098             UnmapViewOfFile (buf);
1099             break;
1100           }
1101       }
1102
1103       debug_printf ("%s is possibly a script", real_path.get_win32 ());
1104
1105       ptr = buf;
1106       if (*ptr++ == '#' && *ptr++ == '!')
1107         {
1108           ptr += strspn (ptr, " \t");
1109           size_t len = strcspn (ptr, "\r\n");
1110           if (len)
1111             {
1112               char *namebuf = (char *) alloca (len + 1);
1113               memcpy (namebuf, ptr, len);
1114               namebuf[len] = '\0';
1115               for (ptr = pgm = namebuf; *ptr; ptr++)
1116                 if (!arg1 && (*ptr == ' ' || *ptr == '\t'))
1117                   {
1118                     /* Null terminate the initial command and step over any
1119                        additional white space.  If we've hit the end of the
1120                        line, exit the loop.  Otherwise, we've found the first
1121                        argument. Position the current pointer on the last known
1122                        white space. */
1123                     *ptr = '\0';
1124                     char *newptr = ptr + 1;
1125                     newptr += strspn (newptr, " \t");
1126                     if (!*newptr)
1127                       break;
1128                     arg1 = newptr;
1129                     ptr = newptr - 1;
1130                   }
1131             }
1132         }
1133       UnmapViewOfFile (buf);
1134 just_shell:
1135       if (!pgm)
1136         {
1137           if (!p_type_exec)
1138             {
1139               /* Not called from exec[lv]p.  Don't try to treat as script. */
1140               debug_printf ("%s is not a valid executable",
1141                             real_path.get_win32 ());
1142               set_errno (ENOEXEC);
1143               return -1;
1144             }
1145           if (ascii_strcasematch (ext, ".com"))
1146             break;
1147           pgm = (char *) "/bin/sh";
1148           arg1 = NULL;
1149         }
1150
1151       /* Check if script is executable.  Otherwise we start non-executable
1152          scripts successfully, which is incorrect behaviour. */
1153       if (real_path.has_acls ()
1154           && check_file_access (real_path, X_OK, true) < 0)
1155         return -1;      /* errno is already set. */
1156
1157       /* Replace argv[0] with the full path to the script if this is the
1158          first time through the loop. */
1159       replace0_maybe (prog_arg);
1160
1161       /* pointers:
1162        * pgm    interpreter name
1163        * arg1   optional string
1164        */
1165       if (arg1)
1166         unshift (arg1);
1167
1168       /* FIXME: This should not be using FE_NATIVE.  It should be putting
1169          the posix path on the argv list. */
1170       find_exec (pgm, real_path, "PATH=", FE_NATIVE, &ext);
1171       unshift (real_path.get_win32 (), 1);
1172     }
1173   return 0;
1174
1175 err:
1176   __seterrno ();
1177   return -1;
1178 }