3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
23 #include <sys/cygwin.h>
30 #include "child_info.h"
31 #include "shared_info.h"
38 static suffix_info exe_suffixes[] =
41 suffix_info (".exe", 1),
46 static suffix_info dll_suffixes[] =
50 suffix_info (".exe", 1),
55 child_info_spawn *chExeced;
57 /* Add .exe to PROG if not already present and see if that exists.
58 If not, return PROG (converted from posix to win32 rules if necessary).
59 The result is always BUF.
61 Returns (possibly NULL) suffix */
64 perhaps_suffix (const char *prog, path_conv& buf, int& err, unsigned opt)
69 debug_printf ("prog '%s'", prog);
70 buf.check (prog, PC_SYM_FOLLOW | PC_NULLEMPTY,
71 (opt & FE_DLL) ? dll_suffixes : exe_suffixes);
78 else if (!buf.exists ())
83 else if (buf.known_suffix)
84 ext = (char *) buf + (buf.known_suffix - buf.get_win32 ());
86 ext = strchr (buf, '\0');
88 debug_printf ("buf %s, suffix found '%s'", (char *) buf, ext);
92 /* Find an executable name, possibly by appending known executable
93 suffixes to it. The win32-translated name is placed in 'buf'.
94 Any found suffix is returned in known_suffix.
96 If the file is not found and !null_if_not_found then the win32 version
97 of name is placed in buf and returned. Otherwise the contents of buf
98 is undefined and NULL is returned. */
100 const char * __stdcall
101 find_exec (const char *name, path_conv& buf, const char *mywinenv,
102 unsigned opt, const char **known_suffix)
104 const char *suffix = "";
105 debug_printf ("find_exec (%s)", name);
106 const char *retval = buf;
107 char tmp[CYG_MAX_PATH];
108 const char *posix = (opt & FE_NATIVE) ? NULL : name;
109 bool has_slash = strchr (name, '/');
112 /* Check to see if file can be opened as is first.
113 Win32 systems always check . first, but PATH may not be set up to
115 if ((has_slash || opt & FE_CWD)
116 && (suffix = perhaps_suffix (name, buf, err, opt)) != NULL)
118 if (posix && !has_slash)
122 strcpy (tmp + 2, name);
130 const char *posix_path;
132 posix = (opt & FE_NATIVE) ? NULL : tmp;
134 if (strchr (mywinenv, '/'))
136 /* it's not really an environment variable at all */
137 int n = cygwin_posix_to_win32_path_list_buf_size (mywinenv);
138 char *s = (char *) alloca (n + 1);
139 if (cygwin_posix_to_win32_path_list (mywinenv, s))
142 posix_path = mywinenv - 1;
144 else if (has_slash || strchr (name, '\\') || isdrive (name)
145 || !(winpath = getwinenv (mywinenv))
146 || !(path = winpath->get_native ()) || *path == '\0')
147 /* Return the error condition if this is an absolute path or if there
148 is no PATH to search. */
151 posix_path = winpath->get_posix () - 1;
153 debug_printf ("%s%s", mywinenv, path);
154 /* Iterate over the specified path, looking for the file with and without
155 executable extensions. */
159 char *eotmp = strccpy (tmp, &path, ';');
160 /* An empty path or '.' means the current directory, but we've
161 already tried that. */
162 if (opt & FE_CWD && (tmp[0] == '\0' || (tmp[0] == '.' && tmp[1] == '\0')))
166 strcpy (eotmp, name);
168 debug_printf ("trying %s", tmp);
170 if ((suffix = perhaps_suffix (tmp, buf, err, opt)) != NULL)
172 if (buf.has_acls () && allow_ntsec && check_file_access (buf, X_OK))
177 eotmp = strccpy (tmp, &posix_path, ':');
181 strcpy (eotmp, name);
186 while (*path && *++path && (posix_path = strchr (posix_path, ':')));
190 /* Couldn't find anything in the given path.
191 Take the appropriate action based on null_if_not_found. */
194 else if (opt & FE_NATIVE)
201 buf.set_path (posix);
202 debug_printf ("%s = find_exec (%s)", (char *) buf, name);
204 *known_suffix = suffix ?: strchr (buf, '\0');
210 /* Utility for spawn_guts. */
213 handle (int fd, bool writing)
216 cygheap_fdget cfd (fd);
219 h = INVALID_HANDLE_VALUE;
220 else if (cfd->close_on_exec ())
221 h = INVALID_HANDLE_VALUE;
223 h = cfd->get_handle ();
225 h = cfd->get_output_handle ();
231 iscmd (const char *argv0, const char *what)
234 n = strlen (argv0) - strlen (what);
235 if (n >= 2 && argv0[1] != ':')
237 return n >= 0 && strcasematch (argv0 + n, what) &&
238 (n == 0 || isdirsep (argv0[n - 1]));
241 struct pthread_cleanup
243 _sig_func_ptr oldint;
244 _sig_func_ptr oldquit;
246 pthread_cleanup (): oldint (NULL), oldquit (NULL), oldmask ((sigset_t) -1) {}
250 do_cleanup (void *args)
252 # define cleanup ((pthread_cleanup *) args)
253 if (cleanup->oldmask != (sigset_t) -1)
255 signal (SIGINT, cleanup->oldint);
256 signal (SIGQUIT, cleanup->oldquit);
257 sigprocmask (SIG_SETMASK, &(cleanup->oldmask), NULL);
264 spawn_guts (const char * prog_arg, const char *const *argv,
265 const char *const envp[], int mode, int __stdin, int __stdout)
271 if (prog_arg == NULL)
273 syscall_printf ("prog_arg is NULL");
278 syscall_printf ("spawn_guts (%d, %.9500s)", mode, prog_arg);
282 syscall_printf ("argv is NULL");
287 /* FIXME: There is a small race here and FIXME: not thread safe! */
289 pthread_cleanup cleanup;
290 if (mode == _P_SYSTEM)
292 sigset_t child_block;
293 cleanup.oldint = signal (SIGINT, SIG_IGN);
294 cleanup.oldquit = signal (SIGQUIT, SIG_IGN);
295 sigemptyset (&child_block);
296 sigaddset (&child_block, SIGCHLD);
297 sigprocmask (SIG_BLOCK, &child_block, &cleanup.oldmask);
299 pthread_cleanup_push (do_cleanup, (void *) &cleanup);
303 char *envblock = NULL;
305 bool reset_sendsig = false;
310 cygheap_exec_info *moreinfo;
312 bool null_app_name = false;
313 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
316 HANDLE orig_wr_proc_pipe = NULL;
319 if (efault.faulted ())
321 if (get_errno () == ENOMEM)
329 child_info_types chtype;
330 if (mode != _P_OVERLAY)
335 moreinfo = (cygheap_exec_info *) ccalloc (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info));
336 moreinfo->old_title = NULL;
338 /* CreateProcess takes one long string that is the command line (sigh).
339 We need to quote any argument that has whitespace or embedded "'s. */
342 for (ac = 0; argv[ac]; ac++)
345 newargv.set (ac, argv);
349 if ((ext = perhaps_suffix (prog_arg, real_path, err, FE_NADA)) == NULL)
357 wascygexec = real_path.iscygexec ();
358 res = newargv.fixup (prog_arg, real_path, ext);
363 if (ac == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
364 (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
366 real_path.check (prog_arg);
368 if (!real_path.error)
369 one_line.add (real_path);
371 one_line.add (argv[0]);
374 one_line.add (argv[1]);
376 one_line.add (argv[2]);
377 strcpy (real_path, argv[0]);
378 null_app_name = true;
384 else if (!one_line.fromargv (newargv, real_path, real_path.iscygexec ()))
391 newargv.all_calloced ();
392 moreinfo->argc = newargv.argc;
393 moreinfo->argv = newargv;
395 if (mode != _P_OVERLAY ||
396 !DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc,
397 &moreinfo->myself_pinfo, 0,
398 TRUE, DUPLICATE_SAME_ACCESS))
399 moreinfo->myself_pinfo = NULL;
401 VerifyHandle (moreinfo->myself_pinfo);
404 PROCESS_INFORMATION pi;
405 pi.hProcess = pi.hThread = NULL;
406 pi.dwProcessId = pi.dwThreadId = 0;
407 si.lpReserved = NULL;
410 /* Set up needed handles for stdio */
411 si.dwFlags = STARTF_USESTDHANDLES;
412 si.hStdInput = handle ((__stdin < 0 ? 0 : __stdin), false);
413 si.hStdOutput = handle ((__stdout < 0 ? 1 : __stdout), true);
414 si.hStdError = handle (2, true);
417 if (!wincap.pty_needs_alloc_console () && newargv.iscui && myself->ctty == -1)
419 si.dwFlags |= STARTF_USESHOWWINDOW;
420 si.wShowWindow = SW_HIDE;
423 c_flags = GetPriorityClass (hMainProc);
424 sigproc_printf ("priority class %d", c_flags);
425 c_flags |= CREATE_SEPARATE_WOW_VDM;
427 if (mode == _P_DETACH)
428 c_flags |= DETACHED_PROCESS;
430 set_console_state_for_spawn (real_path.iscygexec ());
432 if (mode != _P_OVERLAY)
433 myself->exec_sendsig = NULL;
436 /* Reset sendsig so that any process which wants to send a signal
437 to this pid will wait for the new process to become active.
438 Save the old value in case the exec fails. */
439 if (!myself->exec_sendsig)
441 myself->exec_sendsig = myself->sendsig;
442 myself->exec_dwProcessId = myself->dwProcessId;
443 myself->sendsig = NULL;
444 reset_sendsig = true;
446 /* Save a copy of a handle to the current process around the first time we
447 exec so that the pid will not be reused. Why did I stop cygwin from
448 generating its own pids again? */
449 if (cygheap->pid_handle)
450 /* already done previously */;
451 else if (DuplicateHandle (hMainProc, hMainProc, hMainProc, &cygheap->pid_handle,
452 PROCESS_QUERY_INFORMATION, TRUE, 0))
453 ProtectHandleINH (cygheap->pid_handle);
455 system_printf ("duplicate to pid_handle failed, %E");
458 /* Some file types (currently only sockets) need extra effort in the parent
459 after CreateProcess and before copying the datastructures to the child.
460 So we have to start the child in suspend state, unfortunately, to avoid
462 if (!newargv.win16_exe
463 && (wincap.start_proc_suspended () || mode != _P_OVERLAY
464 || cygheap->fdtab.need_fixup_before ()))
465 c_flags |= CREATE_SUSPENDED;
467 runpath = null_app_name ? NULL : (const char *) real_path;
469 syscall_printf ("null_app_name %d (%s, %.9500s)", null_app_name, runpath, one_line.buf);
471 cygbench ("spawn-guts");
473 cygheap->fdtab.set_file_pointers_for_exec ();
475 moreinfo->envp = build_env (envp, envblock, moreinfo->envc, real_path.iscygexec ());
476 if (!moreinfo->envp || !envblock)
482 ch.set (chtype, real_path.iscygexec ());
483 ch.moreinfo = moreinfo;
484 ch.__stdin = __stdin;
485 ch.__stdout = __stdout;
487 si.lpReserved2 = (LPBYTE) &ch;
488 si.cbReserved2 = sizeof (ch);
490 /* When ruid != euid we create the new process under the current original
491 account and impersonate in child, this way maintaining the different
492 effective vs. real ids.
493 FIXME: If ruid != euid and ruid != saved_uid we currently give
494 up on ruid. The new process will have ruid == euid. */
496 cygheap->user.deimpersonate ();
498 if (!cygheap->user.issetuid ()
499 || (cygheap->user.saved_uid == cygheap->user.real_uid
500 && cygheap->user.saved_gid == cygheap->user.real_gid
501 && !cygheap->user.groups.issetgroups ()))
503 rc = CreateProcess (runpath, /* image name - with full path */
504 one_line.buf, /* what was passed to exec */
505 &sec_none_nih,/* process security attrs */
506 &sec_none_nih,/* thread security attrs */
507 TRUE, /* inherit handles from parent */
509 envblock, /* environment */
510 wincap.is_winnt () || real_path.iscygexec () ?
511 NULL : cygheap->cwd.win32,
517 /* Give access to myself */
518 if (mode == _P_OVERLAY)
521 /* allow the child to interact with our window station/desktop */
523 SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
528 hwst = GetProcessWindowStation ();
529 SetUserObjectSecurity (hwst, &dsi, get_null_sd ());
530 GetUserObjectInformation (hwst, UOI_NAME, wstname, 1024, &n);
531 hdsk = GetThreadDesktop (GetCurrentThreadId ());
532 SetUserObjectSecurity (hdsk, &dsi, get_null_sd ());
533 GetUserObjectInformation (hdsk, UOI_NAME, dskname, 1024, &n);
534 strcat (wstname, "\\");
535 strcat (wstname, dskname);
536 si.lpDesktop = wstname;
538 rc = CreateProcessAsUser (cygheap->user.primary_token (),
539 runpath, /* image name - with full path */
540 one_line.buf, /* what was passed to exec */
541 &sec_none_nih, /* process security attrs */
542 &sec_none_nih, /* thread security attrs */
543 TRUE, /* inherit handles from parent */
545 envblock, /* environment */
546 wincap.is_winnt () || real_path.iscygexec () ?
547 NULL : cygheap->cwd.win32,
552 /* Restore impersonation. In case of _P_OVERLAY this isn't
553 allowed since it would overwrite child data. */
554 if (mode != _P_OVERLAY || !rc)
555 cygheap->user.reimpersonate ();
557 /* Set errno now so that debugging messages from it appear before our
558 final debugging message [this is a general rule for debugging
563 syscall_printf ("CreateProcess failed, %E");
564 /* If this was a failed exec, restore the saved sendsig. */
567 myself->sendsig = myself->exec_sendsig;
568 myself->exec_sendsig = NULL;
571 if (moreinfo->myself_pinfo)
572 CloseHandle (moreinfo->myself_pinfo);
576 if (!(c_flags & CREATE_SUSPENDED))
577 strace.write_childpid (ch, pi.dwProcessId);
579 /* Fixup the parent data structures if needed and resume the child's
581 if (cygheap->fdtab.need_fixup_before ())
582 cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
584 if (mode != _P_OVERLAY)
585 cygpid = cygwin_pid (pi.dwProcessId);
587 cygpid = myself->pid;
589 /* We print the original program name here so the user can see that too. */
590 syscall_printf ("%d = spawn_guts (%s, %.9500s)",
591 rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf);
593 /* Name the handle similarly to proc_subproc. */
594 ProtectHandle1 (pi.hProcess, childhProc);
598 if (mode == _P_OVERLAY)
600 chExeced = &ch; /* FIXME: there's a race here if a user sneaks in CTRL-C */
601 myself->dwProcessId = pi.dwProcessId;
603 myself.hProcess = hExeced = pi.hProcess;
604 strcpy (myself->progname, real_path); // FIXME: race?
605 sigproc_printf ("new process name %s", myself->progname);
606 /* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
607 process. So, we need to wait around until the process we've just "execed"
608 dies. Use our own wait facility to wait for our own pid to exit (there
609 is some minor special case code in proc_waiter and friends to accommodate
612 If wr_proc_pipe exists, then it should be duplicated to the child.
613 If the child has exited already, that's ok. The parent will pick up
614 on this fact when we exit. dup_proc_pipe will close our end of the pipe.
615 Note that wr_proc_pipe may also be == INVALID_HANDLE_VALUE. That will make
616 dup_proc_pipe essentially a no-op. */
617 if (!newargv.win16_exe && myself->wr_proc_pipe)
621 myself->sync_proc_pipe (); /* Make sure that we own wr_proc_pipe
622 just in case we've been previously
625 orig_wr_proc_pipe = myself->dup_proc_pipe (pi.hProcess);
633 myself->set_has_pgid_children ();
634 ProtectHandle (pi.hThread);
635 pinfo child (cygpid, PID_IN_USE);
638 syscall_printf ("pinfo failed");
639 if (get_errno () != ENOMEM)
644 child->dwProcessId = pi.dwProcessId;
645 child.hProcess = pi.hProcess;
647 strcpy (child->progname, real_path);
648 /* FIXME: This introduces an unreferenced, open handle into the child.
649 The purpose is to keep the pid shared memory open so that all of
650 the fields filled out by child.remember do not disappear and so there
651 is not a brief period during which the pid is not available.
652 However, we should try to find another way to do this eventually. */
653 DuplicateHandle (hMainProc, child.shared_handle (), pi.hProcess,
654 NULL, 0, 0, DUPLICATE_SAME_ACCESS);
655 child->start_time = time (NULL); /* Register child's starting time. */
656 child->nice = myself->nice;
657 if (!child.remember (mode == _P_DETACH))
659 /* FIXME: Child in strange state now */
660 CloseHandle (pi.hProcess);
661 ForceCloseHandle (pi.hThread);
668 /* Start the child running */
669 if (c_flags & CREATE_SUSPENDED)
671 ResumeThread (pi.hThread);
672 strace.write_childpid (ch, pi.dwProcessId);
674 ForceCloseHandle (pi.hThread);
676 sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
678 if ((mode == _P_DETACH || mode == _P_NOWAIT) && !ch.iscygwin ())
681 synced = ch.sync (pi.dwProcessId, pi.hProcess, INFINITE);
686 myself.hProcess = pi.hProcess;
689 if (orig_wr_proc_pipe)
691 myself->wr_proc_pipe_owner = GetCurrentProcessId ();
692 myself->wr_proc_pipe = orig_wr_proc_pipe;
694 DWORD res = ch.proc_retry (pi.hProcess);
700 close_all_files (true);
704 close_all_files (true);
705 if (!myself->wr_proc_pipe
706 && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
708 extern bool is_toplevel_proc;
709 is_toplevel_proc = true;
710 myself.remember (false);
711 waitpid (myself->pid, &res, 0);
714 myself.exit (EXITCODE_NOSET);
718 if (waitpid (cygpid, &res, 0) != cygpid)
722 res = 0; /* Lost all memory of this child. */
736 pthread_cleanup_pop (1);
742 cwait (int *result, int pid, int)
744 return waitpid (pid, result, 0);
748 * Helper function for spawn runtime calls.
749 * Doesn't search the path.
753 spawnve (int mode, const char *path, const char *const *argv,
754 const char *const *envp)
758 vfork_save *vf = vfork_storage.val ();
760 if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
766 syscall_printf ("spawnve (%s, %s, %x)", path, argv[0], envp);
771 /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
772 /* Just act as an exec if _P_OVERLAY set. */
773 spawn_guts (path, argv, envp, mode);
774 /* Errno should be set by spawn_guts. */
783 ret = spawn_guts (path, argv, envp, mode);
789 debug_printf ("longjmping due to vfork");
790 vf->restore_pid (ret);
804 * spawn functions as implemented in the MS runtime library.
805 * Most of these based on (and copied from) newlib/libc/posix/execXX.c
809 spawnl (int mode, const char *path, const char *arg0, ...)
813 const char *argv[256];
815 va_start (args, arg0);
820 argv[i] = va_arg (args, const char *);
821 while (argv[i++] != NULL);
825 return spawnve (mode, path, (char * const *) argv, cur_environ ());
829 spawnle (int mode, const char *path, const char *arg0, ...)
833 const char * const *envp;
834 const char *argv[256];
836 va_start (args, arg0);
841 argv[i] = va_arg (args, const char *);
842 while (argv[i++] != NULL);
844 envp = va_arg (args, const char * const *);
847 return spawnve (mode, path, (char * const *) argv, (char * const *) envp);
851 spawnlp (int mode, const char *path, const char *arg0, ...)
855 const char *argv[256];
857 va_start (args, arg0);
862 argv[i] = va_arg (args, const char *);
863 while (argv[i++] != NULL);
867 return spawnvpe (mode, path, (char * const *) argv, cur_environ ());
871 spawnlpe (int mode, const char *path, const char *arg0, ...)
875 const char * const *envp;
876 const char *argv[256];
878 va_start (args, arg0);
883 argv[i] = va_arg (args, const char *);
884 while (argv[i++] != NULL);
886 envp = va_arg (args, const char * const *);
889 return spawnvpe (mode, path, (char * const *) argv, envp);
893 spawnv (int mode, const char *path, const char * const *argv)
895 return spawnve (mode, path, argv, cur_environ ());
899 spawnvp (int mode, const char *path, const char * const *argv)
901 return spawnvpe (mode, path, argv, cur_environ ());
905 spawnvpe (int mode, const char *file, const char * const *argv,
906 const char * const *envp)
909 return spawnve (mode, find_exec (file, buf), argv, envp);
913 av::fixup (const char *prog_arg, path_conv& real_path, const char *ext)
916 bool exeext = strcasematch (ext, ".exe");
917 if (exeext && real_path.iscygexec () || strcasematch (ext, ".bat"))
919 if (!*ext && ((p = ext - 4) > (char *) real_path)
920 && (strcasematch (p, ".bat") || strcasematch (p, ".cmd")
921 || strcasematch (p, ".btm")))
929 HANDLE h = CreateFile (real_path, GENERIC_READ,
930 FILE_SHARE_READ | FILE_SHARE_WRITE,
931 &sec_none_nih, OPEN_EXISTING,
932 FILE_ATTRIBUTE_NORMAL, 0);
933 if (h == INVALID_HANDLE_VALUE)
936 HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL);
940 /* ERROR_FILE_INVALID indicates very likely an empty file. */
941 if (GetLastError () == ERROR_FILE_INVALID)
943 debug_printf ("zero length file, treat as script.");
948 buf = (char *) MapViewOfFile(hm, FILE_MAP_READ, 0, 0, 0);
955 if (efault.faulted ())
957 UnmapViewOfFile (buf);
958 real_path.set_cygexec (false);
961 if (buf[0] == 'M' && buf[1] == 'Z')
964 unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
965 win16_exe = off < sizeof (IMAGE_DOS_HEADER);
967 real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL, subsys));
969 real_path.set_cygexec (false);
970 UnmapViewOfFile (buf);
971 iscui = subsys == IMAGE_SUBSYSTEM_WINDOWS_CUI;
976 debug_printf ("%s is possibly a script", (char *) real_path);
979 if (*ptr++ == '#' && *ptr++ == '!')
981 ptr += strspn (ptr, " \t");
982 size_t len = strcspn (ptr, "\r\n");
985 char *namebuf = (char *) alloca (len + 1);
986 memcpy (namebuf, ptr, len);
988 for (ptr = pgm = namebuf; *ptr; ptr++)
989 if (!arg1 && (*ptr == ' ' || *ptr == '\t'))
991 /* Null terminate the initial command and step over any additional white
992 space. If we've hit the end of the line, exit the loop. Otherwise,
993 we've found the first argument. Position the current pointer on the
994 last known white space. */
996 char *newptr = ptr + 1;
997 newptr += strspn (newptr, " \t");
1005 UnmapViewOfFile (buf);
1009 if (strcasematch (ext, ".com"))
1011 pgm = (char *) "/bin/sh";
1015 /* Replace argv[0] with the full path to the script if this is the
1016 first time through the loop. */
1017 replace0_maybe (prog_arg);
1020 * pgm interpreter name
1021 * arg1 optional string
1026 /* FIXME: This should not be using FE_NATIVE. It should be putting
1027 the posix path on the argv list. */
1028 find_exec (pgm, real_path, "PATH=", FE_NATIVE, &ext);
1029 unshift (real_path, 1);