3 Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
24 extern BOOL allow_ntsec;
26 #define LINE_BUF_CHUNK (MAX_PATH * 2)
28 suffix_info std_suffixes[] =
30 suffix_info (".exe", 1), suffix_info ("", 1),
31 suffix_info (".com"), suffix_info (".cmd"),
32 suffix_info (".bat"), suffix_info (".dll"),
36 /* Add .exe to PROG if not already present and see if that exists.
37 If not, return PROG (converted from posix to win32 rules if necessary).
38 The result is always BUF.
40 Returns (possibly NULL) suffix */
43 perhaps_suffix (const char *prog, path_conv &buf)
47 debug_printf ("prog '%s'", prog);
48 buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes);
50 if (buf.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)
52 else if (buf.known_suffix)
53 ext = buf + (buf.known_suffix - buf.get_win32 ());
55 ext = strchr (buf, '\0');
57 debug_printf ("buf %s, suffix found '%s'", (char *) buf, ext);
61 /* Find an executable name, possibly by appending known executable
62 suffixes to it. The win32-translated name is placed in 'buf'.
63 Any found suffix is returned in known_suffix.
65 If the file is not found and !null_if_not_found then the win32 version
66 of name is placed in buf and returned. Otherwise the contents of buf
67 is undefined and NULL is returned. */
69 const char * __stdcall
70 find_exec (const char *name, path_conv& buf, const char *mywinenv,
71 int null_if_notfound, const char **known_suffix)
73 const char *suffix = "";
74 debug_printf ("find_exec (%s)", name);
77 /* Check to see if file can be opened as is first.
78 Win32 systems always check . first, but PATH may not be set up to
80 if ((suffix = perhaps_suffix (name, buf)) != NULL)
87 /* Return the error condition if this is an absolute path or if there
88 is no PATH to search. */
89 if (strchr (name, '/') || strchr (name, '\\') ||
91 !(winpath = getwinenv (mywinenv)) ||
92 !(path = winpath->get_native ()) ||
96 debug_printf ("%s%s", mywinenv, path);
98 /* Iterate over the specified path, looking for the file with and
99 without executable extensions. */
102 char *eotmp = strccpy (tmp, &path, ';');
103 /* An empty path or '.' means the current directory, but we've
104 already tried that. */
105 if (tmp[0] == '\0' || (tmp[0] == '.' && tmp[1] == '\0'))
109 strcpy (eotmp, name);
111 debug_printf ("trying %s", tmp);
113 if ((suffix = perhaps_suffix (tmp, buf)) != NULL)
116 while (*path && *++path);
119 /* Couldn't find anything in the given path.
120 Take the appropriate action based on null_if_not_found. */
121 if (null_if_notfound)
127 debug_printf ("%s = find_exec (%s)", (char *) buf, name);
129 *known_suffix = suffix ?: strchr (buf, '\0');
133 /* Utility for spawn_guts. */
136 handle (int n, int direction)
138 fhandler_base *fh = dtable[n];
141 return INVALID_HANDLE_VALUE;
142 if (fh->get_close_on_exec ())
143 return INVALID_HANDLE_VALUE;
145 return fh->get_handle ();
146 return fh->get_output_handle ();
149 /* Cover function for CreateProcess.
151 This function is used by both the routines that search $PATH and those
152 that do not. This should work out ok as according to the documentation,
153 CreateProcess only searches $PATH if PROG has no directory elements.
155 Spawning doesn't fit well with Posix's fork/exec (one can argue the merits
156 of either but that's beside the point). If we're exec'ing we want to
157 record the child pid for fork. If we're spawn'ing we don't want to do
158 this. It is up to the caller to handle both cases.
160 The result is the process id. The handle of the created process is
164 HANDLE NO_COPY hExeced = NULL;
165 DWORD NO_COPY exec_exit = 0;
168 iscmd (const char *argv0, const char *what)
171 n = strlen (argv0) - strlen (what);
172 if (n >= 2 && argv0[1] != ':')
174 return n >= 0 && strcasematch (argv0 + n, what) &&
175 (n == 0 || isdirsep (argv0[n - 1]));
184 linebuf () : ix (0), buf (NULL), alloced (0)
187 ~linebuf () {/* if (buf) free (buf);*/}
188 void add (const char *what, int len);
189 void add (const char *what) {add (what, strlen (what));}
190 void prepend (const char *what, int len);
194 linebuf::add (const char *what, int len)
197 if ((newix = ix + len) >= alloced || !buf)
199 alloced += LINE_BUF_CHUNK + newix;
200 buf = (char *) realloc (buf, alloced + 1);
202 memcpy (buf + ix, what, len);
208 linebuf::prepend (const char *what, int len)
212 if ((newix = ix + len) >= alloced)
214 alloced += LINE_BUF_CHUNK + newix;
215 buf = (char *) realloc (buf, alloced + 1);
218 if ((buflen = strlen (buf)))
219 memmove (buf + len, buf, buflen + 1);
222 memcpy (buf, what, len);
226 static HANDLE hexec_proc = NULL;
229 exec_fixup_after_fork ()
232 CloseHandle (hexec_proc);
237 spawn_guts (HANDLE hToken, const char * prog_arg, const char *const *argv,
238 const char *const envp[], int mode)
249 if (prog_arg == NULL)
251 syscall_printf ("prog_arg is NULL");
256 syscall_printf ("spawn_guts (%.132s)", prog_arg);
260 syscall_printf ("argv is NULL");
265 /* CreateProcess takes one long string that is the command line (sigh).
266 We need to quote any argument that has whitespace or embedded "'s. */
268 for (argc = 0; argv[argc]; argc++)
272 path_conv real_path_buf;
276 if (argc == 3 && argv[1][0] == '/' && argv[1][1] == 'c' &&
277 (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
279 one_line.add (argv[0]);
281 one_line.add (argv[1]);
284 one_line.add (argv[2]);
285 strcpy (real_path_buf, argv[0]);
286 goto skip_arg_parsing;
289 real_path = real_path_buf;
291 const char *saved_prog_arg;
292 const char *newargv0, **firstarg;
295 if ((ext = perhaps_suffix (prog_arg, real_path_buf)) == NULL)
302 saved_prog_arg = prog_arg;
304 firstarg = &newargv0;
306 /* If the file name ends in either .exe, .com, .bat, or .cmd we assume
307 that it is NOT a script file */
310 HANDLE hnd = CreateFileA (real_path,
312 FILE_SHARE_READ | FILE_SHARE_WRITE,
315 FILE_ATTRIBUTE_NORMAL,
317 if (hnd == INVALID_HANDLE_VALUE)
325 char buf[2 * MAX_PATH + 1];
326 buf[0] = buf[1] = buf[2] = buf[sizeof(buf) - 1] = '\0';
327 if (! ReadFile (hnd, buf, sizeof (buf) - 1, &done, 0))
336 if (buf[0] == 'M' && buf[1] == 'Z')
339 debug_printf ("%s is a script", prog_arg);
341 char *ptr, *pgm, *arg1;
343 if (buf[0] != '#' || buf[1] != '!')
345 strcpy (buf, "sh"); /* shell script without magic */
353 pgm += strspn (pgm, " \t");
354 for (ptr = pgm, arg1 = NULL;
355 *ptr && *ptr != '\r' && *ptr != '\n';
357 if (!arg1 && (*ptr == ' ' || *ptr == '\t'))
359 /* Null terminate the initial command and step over
360 any additional white space. If we've hit the
361 end of the line, exit the loop. Otherwise, position
362 we've found the first argument. Position the current
363 pointer on the last known white space. */
365 char *newptr = ptr + 1;
366 newptr += strspn (newptr, " \t");
367 if (!*newptr || *newptr == '\r' || *newptr == '\n')
377 char buf2[MAX_PATH + 1];
380 * pgm interpreter name
381 * arg1 optional string
386 one_line.prepend (" ", 1);
389 one_line.prepend ("\" ", 2);
390 one_line.prepend (arg1, strlen (arg1));
391 one_line.prepend (" \"", 2);
394 find_exec (pgm, real_path_buf, "PATH=", 0, &ext);
395 cygwin_conv_to_posix_path (real_path, buf2);
396 one_line.prepend (buf2, strlen (buf2));
398 /* If script had absolute path, add it to script name now!
399 * This is necessary if script has been found via PATH.
400 * For example, /usr/local/bin/tkman started as "tkman":
401 * #!/usr/local/bin/wish -f
403 * We should run /usr/local/bin/wish -f /usr/local/bin/tkman,
404 * but not /usr/local/bin/wish -f tkman!
405 * We don't modify anything, if script has qulified path.
408 *firstarg = saved_prog_arg;
410 debug_printf ("prog_arg '%s', copy '%s'", prog_arg, one_line.buf);
414 for (; *argv; argv++)
417 const char *a = newargv0 ?: *argv;
422 int len = strlen (a);
423 if (len != 0 && !strpbrk (a, " \t\n\r\""))
424 one_line.add (a, len);
427 one_line.add ("\"", 1);
428 for (; (p = strpbrk (a, "\"\\")); a = ++p)
430 one_line.add (a, p - a);
431 if (*p == '\\' || *p == '"')
432 one_line.add ("\\", 1);
437 one_line.add ("\"", 1);
440 one_line.add (" ", 1);
446 one_line.buf[one_line.ix - 1] = '\0';
448 one_line.add ("", 1);
452 PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
453 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
454 si.lpReserved = NULL;
456 si.dwFlags = STARTF_USESTDHANDLES;
457 si.hStdInput = handle (0, 0); /* Get input handle */
458 si.hStdOutput = handle (1, 1); /* Get output handle */
459 si.hStdError = handle (2, 1); /* Get output handle */
462 /* Pass fd table to a child */
465 int len = dtable.linearize_fd_array (0, 0);
469 system_printf ("FATAL error in linearize_fd_array");
472 int titlelen = 1 + (old_title && mode == _P_OVERLAY ? strlen (old_title) : 0);
473 si.cbReserved2 = len + titlelen + sizeof(child_info);
474 si.lpReserved2 = (LPBYTE) alloca (si.cbReserved2);
476 # define ciresrv ((child_info *)si.lpReserved2)
479 if (mode != _P_OVERLAY)
483 spr = CreateEvent(&sec_all, TRUE, FALSE, NULL);
488 init_child_info (chtype, ciresrv, (mode == _P_OVERLAY) ? myself->pid : 1, spr);
490 LPBYTE resrv = si.lpReserved2 + sizeof *ciresrv;
493 if (dtable.linearize_fd_array (resrv, len) < 0)
495 system_printf ("FATAL error in second linearize_fd_array");
500 strcpy ((char *) resrv + len, old_title);
504 /* We print the translated program and arguments here so the user can see
505 what was done to it. */
506 syscall_printf ("spawn_guts (%s, %.132s)", real_path, one_line.buf);
508 int flags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED |
509 GetPriorityClass (hMainProc);
511 if (mode == _P_DETACH || !set_console_state_for_spawn ())
512 flags |= DETACHED_PROCESS;
514 /* Build windows style environment list */
515 char *envblock = winenv (envp, 0);
517 /* Preallocated buffer for `sec_user' call */
520 if (!hToken && myself->token != INVALID_HANDLE_VALUE)
521 hToken = myself->token;
523 if (mode == _P_OVERLAY && !hexec_proc &&
524 !DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
525 TRUE, DUPLICATE_SAME_ACCESS))
526 system_printf ("couldn't save current process handle %p, %E", hMainProc);
530 /* allow the child to interact with our window station/desktop */
532 SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
537 hwst = GetProcessWindowStation();
538 SetUserObjectSecurity(hwst, &dsi, get_null_sd ());
539 GetUserObjectInformation(hwst, UOI_NAME, wstname, 1024, &n);
540 hdsk = GetThreadDesktop(GetCurrentThreadId());
541 SetUserObjectSecurity(hdsk, &dsi, get_null_sd ());
542 GetUserObjectInformation(hdsk, UOI_NAME, dskname, 1024, &n);
543 strcat (wstname, "\\");
544 strcat (wstname, dskname);
545 si.lpDesktop = wstname;
550 if (GetTokenInformation (hToken, TokenUser,
551 (LPVOID) &tu, sizeof tu,
553 sid = ((TOKEN_USER *) &tu)->User.Sid;
555 system_printf ("GetTokenInformation: %E");
557 /* Retrieve security attributes before setting psid to NULL
558 since it's value is needed by `sec_user'. */
559 PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
560 ? sec_user (sa_buf, sid)
563 /* Remove impersonation */
564 uid_t uid = geteuid();
565 if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
566 seteuid (myself->orig_uid);
568 /* Load users registry hive. */
569 load_registry_hive (sid);
571 rc = CreateProcessAsUser (hToken,
572 real_path, /* image name - with full path */
573 one_line.buf, /* what was passed to exec */
574 sec_attribs, /* process security attrs */
575 sec_attribs, /* thread security attrs */
576 TRUE, /* inherit handles from parent */
578 envblock,/* environment */
579 0, /* use current drive/directory */
582 /* Restore impersonation. In case of _P_OVERLAY this isn't
583 allowed since it would overwrite child data. */
584 if (mode != _P_OVERLAY
585 && myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
589 rc = CreateProcessA (real_path, /* image name - with full path */
590 one_line.buf, /* what was passed to exec */
591 /* process security attrs */
592 allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
593 /* thread security attrs */
594 allow_ntsec ? sec_user (sa_buf) : &sec_all_nih,
595 TRUE, /* inherit handles from parent */
597 envblock,/* environment */
598 0, /* use current drive/directory */
606 /* Set errno now so that debugging messages from it appear before our
607 final debugging message [this is a general rule for debugging
614 ForceCloseHandle (spr);
616 syscall_printf ("CreateProcess failed, %E");
620 if (mode == _P_OVERLAY)
621 cygpid = myself->pid;
623 cygpid = cygwin_pid (pi.dwProcessId);
625 /* We print the original program name here so the user can see that too. */
626 syscall_printf ("%d = spawn_guts (%s, %.132s)",
627 rc ? cygpid : (unsigned int) -1,
628 prog_arg, one_line.buf);
631 /* Name the handle similarly to proc_subproc. */
632 ProtectHandle1 (pi.hProcess, childhProc);
633 ProtectHandle (pi.hThread);
636 if (mode == _P_OVERLAY)
639 strcpy (myself->progname, real_path_buf);
641 hExeced = pi.hProcess;
643 /* Set up child's signal handlers */
644 /* CGF FIXME - consolidate with signal stuff below */
645 for (i = 0; i < NSIG; i++)
647 myself->getsig(i).sa_mask = 0;
648 if (myself->getsig(i).sa_handler != SIG_IGN || (mode != _P_OVERLAY))
649 myself->getsig(i).sa_handler = SIG_DFL;
654 pinfo child (cygpid, 1);
658 syscall_printf ("-1 = spawnve (), process table full");
661 child->username[0] = '\0';
662 child->progname[0] = '\0';
663 // CGF FIXME -- need to do this? strcpy (child->progname, path);
664 // CGF FIXME -- need to do this? memcpy (child->username, myself->username, MAX_USER_NAME);
665 child->ppid = myself->pid;
666 child->uid = myself->uid;
667 child->gid = myself->gid;
668 child->pgid = myself->pgid;
669 child->sid = myself->sid;
670 child->ctty = myself->ctty;
671 child->umask = myself->umask;
672 child->process_state |= PID_INITIALIZING;
673 memcpy (child->sidbuf, myself->sidbuf, MAX_SID_LEN);
675 child->psid = child->sidbuf;
676 memcpy (child->logsrv, myself->logsrv, MAX_HOST_NAME);
677 memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
678 memcpy (child->root, myself->root, MAX_PATH+1);
679 child->rootlen = myself->rootlen;
680 child->dwProcessId = pi.dwProcessId;
681 child->hProcess = pi.hProcess;
682 child->process_state |= PID_INITIALIZING;
683 for (i = 0; i < NSIG; i++)
685 child->getsig(i).sa_mask = 0;
686 if (child->getsig(i).sa_handler != SIG_IGN || (mode != _P_OVERLAY))
687 child->getsig(i).sa_handler = SIG_DFL;
691 /* Set child->uid to USHRT_MAX to force calling internal_getlogin()
692 from child process. Clear username and psid to play it safe. */
693 child->uid = USHRT_MAX;
699 sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
700 /* Start the child running */
701 ResumeThread (pi.hThread);
702 ForceCloseHandle (pi.hThread);
704 if (hToken && hToken != myself->token)
705 CloseHandle (hToken);
709 if (mode == _P_OVERLAY)
713 HANDLE waitbuf[3] = {pi.hProcess, signal_arrived, spr};
716 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
718 DWORD timeout = INFINITE;
722 for (int i = 0; i < 100; i++)
724 switch (WaitForMultipleObjects (nwait, waitbuf, FALSE, timeout))
727 syscall_printf ("WFMO timed out after signal");
728 if (WaitForSingleObject (pi.hProcess, 0) != WAIT_OBJECT_0)
730 sigproc_printf ("subprocess still alive after signal");
735 sigproc_printf ("subprocess exited after signal");
737 sigproc_printf ("subprocess exited");
738 if (!GetExitCodeProcess (pi.hProcess, &res))
743 if (WaitForSingleObject (spr, 1) == WAIT_OBJECT_0)
744 res |= EXIT_REPARENTING;
745 else if (!(res & EXIT_REPARENTING))
752 case WAIT_OBJECT_0 + 1:
753 sigproc_printf ("signal arrived");
754 ResetEvent (signal_arrived);
756 case WAIT_OBJECT_0 + 2:
757 res = EXIT_REPARENTING;
759 ForceCloseHandle (spr);
764 sigproc_terminate ();
770 system_printf ("wait failed: nwait %d, pid %d, winpid %d, %E",
771 nwait, myself->pid, myself->dwProcessId);
772 system_printf ("waitbuf[0] %p %d", waitbuf[0],
773 GetHandleInformation (waitbuf[0], &r));
774 system_printf ("waitbuf[1] %p = %d", waitbuf[1],
775 GetHandleInformation (waitbuf[1], &r));
783 ForceCloseHandle (spr);
785 sigproc_printf ("res = %x", res);
787 if (res & EXIT_REPARENTING)
789 /* Try to reparent child process.
790 * Make handles to child available to parent process and exit with
791 * EXIT_REPARENTING status. Wait() syscall in parent will then wait
792 * for newly created child.
794 pinfo parent (myself->ppid);
799 HANDLE hP = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
800 parent->dwProcessId);
801 sigproc_printf ("parent handle %p, pid %d", hP, parent->dwProcessId);
802 if (hP == NULL && GetLastError () == ERROR_INVALID_PARAMETER)
807 res = DuplicateHandle (hMainProc, pi.hProcess, hP,
808 &myself->hProcess, 0, FALSE,
809 DUPLICATE_SAME_ACCESS);
810 sigproc_printf ("Dup hP %d", res);
811 ForceCloseHandle (hP);
815 system_printf ("Reparent failed, parent handle %p, %E", hP);
816 system_printf ("my dwProcessId %d, myself->dwProcessId %d",
817 GetCurrentProcessId(), myself->dwProcessId);
818 system_printf ("myself->process_state %x",
819 myself->process_state);
820 system_printf ("myself->hProcess %x", myself->hProcess);
823 res = EXIT_REPARENTING;
824 ForceCloseHandle1 (hExeced, childhProc);
825 hExeced = INVALID_HANDLE_VALUE;
829 ForceCloseHandle1 (hExeced, childhProc);
830 hExeced = INVALID_HANDLE_VALUE; // stop do_exit from attempting to terminate child
834 do_exit (res | EXIT_NOCLOSEALL);
838 waitpid (cygpid, (int *) &res, 0);
839 else if (mode == _P_DETACH)
840 res = 0; /* Lose all memory of this child. */
841 else if ((mode == _P_NOWAIT) || (mode == _P_NOWAITO))
849 cwait (int *result, int pid, int)
851 return waitpid (pid, result, 0);
855 * Helper function for spawn runtime calls.
856 * Doesn't search the path.
860 _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
861 const char *const *envp)
864 vfork_save *vf = vfork_storage.val ();
866 if (vf != NULL && (vf->pid < 0) && mode == _P_OVERLAY)
871 syscall_printf ("_spawnve (%s, %s, %x)", path, argv[0], envp);
876 /* We do not pass _P_SEARCH_PATH here. execve doesn't search PATH.*/
877 /* Just act as an exec if _P_OVERLAY set. */
878 spawn_guts (hToken, path, argv, envp, mode);
879 /* Errno should be set by spawn_guts. */
887 ret = spawn_guts (hToken, path, argv, envp, mode);
903 * spawn functions as implemented in the MS runtime library.
904 * Most of these based on (and copied from) newlib/libc/posix/execXX.c
909 spawnl (int mode, const char *path, const char *arg0, ...)
913 const char *argv[256];
915 va_start (args, arg0);
920 argv[i] = va_arg (args, const char *);
921 while (argv[i++] != NULL);
925 return _spawnve (NULL, mode, path, (char * const *) argv, cur_environ ());
930 spawnle (int mode, const char *path, const char *arg0, ...)
934 const char * const *envp;
935 const char *argv[256];
937 va_start (args, arg0);
942 argv[i] = va_arg (args, const char *);
943 while (argv[i++] != NULL);
945 envp = va_arg (args, const char * const *);
948 return _spawnve (NULL, mode, path, (char * const *) argv,
949 (char * const *) envp);
954 spawnlp (int mode, const char *path, const char *arg0, ...)
958 const char *argv[256];
960 va_start (args, arg0);
965 argv[i] = va_arg (args, const char *);
966 while (argv[i++] != NULL);
970 return spawnvpe (mode, path, (char * const *) argv, cur_environ ());
975 spawnlpe (int mode, const char *path, const char *arg0, ...)
979 const char * const *envp;
980 const char *argv[256];
982 va_start (args, arg0);
987 argv[i] = va_arg (args, const char *);
988 while (argv[i++] != NULL);
990 envp = va_arg (args, const char * const *);
993 return spawnvpe (mode, path, (char * const *) argv, envp);
998 spawnv (int mode, const char *path, const char * const *argv)
1000 return _spawnve (NULL, mode, path, argv, cur_environ ());
1005 spawnve (int mode, const char *path, char * const *argv,
1006 const char * const *envp)
1008 return _spawnve (NULL, mode, path, argv, envp);
1013 spawnvp (int mode, const char *path, const char * const *argv)
1015 return spawnvpe (mode, path, argv, cur_environ ());
1020 spawnvpe (int mode, const char *file, const char * const *argv,
1021 const char * const *envp)
1024 return _spawnve (NULL, mode, find_exec (file, buf), argv, envp);