3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 #include <sys/cygwin.h>
25 #include "child_info.h"
32 static const suffix_info exe_suffixes
[] =
35 suffix_info (".exe", 1),
40 /* Add .exe to PROG if not already present and see if that exists.
41 If not, return PROG (converted from posix to win32 rules if necessary).
42 The result is always BUF.
44 Returns (possibly NULL) suffix */
47 perhaps_suffix (const char *prog
, path_conv
& buf
, int& err
, unsigned opt
)
52 debug_printf ("prog '%s'", prog
);
53 buf
.check (prog
, PC_SYM_FOLLOW
| PC_NULLEMPTY
| PC_POSIX
,
54 (opt
& FE_DLL
) ? stat_suffixes
: exe_suffixes
);
61 else if (!buf
.exists ())
66 else if (buf
.known_suffix ())
67 ext
= buf
.get_win32 () + (buf
.known_suffix () - buf
.get_win32 ());
69 ext
= strchr (buf
.get_win32 (), '\0');
71 debug_printf ("buf %s, suffix found '%s'", (char *) buf
.get_win32 (), ext
);
75 /* Find an executable name, possibly by appending known executable suffixes
76 to it. The path_conv struct 'buf' is filled and contains both, win32 and
77 posix path of the target file. Any found suffix is returned in known_suffix.
78 Eventually the posix path in buf is overwritten with the exact path as it
79 gets constructed for the path search. The reason is that the path is used
80 to create argv[0] in av::setup, and this requires that the filename stays
81 intact, instead of being resolved if the file is a symlink.
83 If the file is not found and !FE_NNF then the POSIX version of name is
84 placed in buf and returned. Otherwise the contents of buf is undefined
85 and NULL is returned. */
87 find_exec (const char *name
, path_conv
& buf
, const char *search
,
88 unsigned opt
, const char **known_suffix
)
90 const char *suffix
= "";
91 const char *retval
= NULL
;
94 char *tmp
= tp
.c_get ();
95 bool has_slash
= !!strpbrk (name
, "/\\");
98 debug_printf ("find_exec (%s)", name
);
100 /* Check to see if file can be opened as is first. */
101 if ((has_slash
|| opt
& FE_CWD
)
102 && (suffix
= perhaps_suffix (name
, buf
, err
, opt
)) != NULL
)
104 /* Overwrite potential symlink target with original path.
105 See comment preceeding this method. */
108 tmp_path
= stpcpy (tmp
, "./");
109 stpcpy (tmp_path
, name
);
111 retval
= buf
.get_posix ();
116 /* If it starts with a slash, it's a PATH-like pathlist. Otherwise it's
117 the name of an environment variable. */
118 if (strchr (search
, '/'))
119 *stpncpy (tmp
, search
, NT_MAX_PATH
- 1) = '\0';
120 else if (has_slash
|| isdrive (name
) || !(path
= getenv (search
)) || !*path
)
123 *stpncpy (tmp
, path
, NT_MAX_PATH
- 1) = '\0';
126 debug_printf ("searchpath %s", path
);
128 tmp_path
= tp
.c_get ();
131 char *eotmp
= strccpy (tmp_path
, &path
, ':');
132 /* An empty path or '.' means the current directory, but we've
133 already tried that. */
134 if ((opt
& FE_CWD
) && (tmp_path
[0] == '\0'
135 || (tmp_path
[0] == '.' && tmp_path
[1] == '\0')))
139 stpcpy (eotmp
, name
);
141 debug_printf ("trying %s", tmp_path
);
145 if ((suffix
= perhaps_suffix (tmp_path
, buf
, err1
, opt
)) != NULL
)
147 if (buf
.has_acls () && check_file_access (buf
, X_OK
, true))
149 /* Overwrite potential symlink target with original path.
150 See comment preceeding this method. */
151 buf
.set_posix (tmp_path
);
152 retval
= buf
.get_posix ();
157 while (*path
&& *++path
);
160 /* Couldn't find anything in the given path.
161 Take the appropriate action based on FE_NNF. */
164 buf
.check (name
, PC_SYM_FOLLOW
| PC_POSIX
);
165 retval
= buf
.get_posix ();
169 debug_printf ("%s = find_exec (%s)", (char *) buf
.get_posix (), name
);
171 *known_suffix
= suffix
?: strchr (buf
.get_win32 (), '\0');
177 /* Utility for child_info_spawn::worker. */
180 handle (int fd
, bool writing
)
183 cygheap_fdget
cfd (fd
);
186 h
= INVALID_HANDLE_VALUE
;
187 else if (cfd
->close_on_exec ())
188 h
= INVALID_HANDLE_VALUE
;
190 h
= cfd
->get_handle_nat ();
192 h
= cfd
->get_output_handle_nat ();
198 is_console_app (WCHAR
*filename
)
201 const int id_offset
= 92;
202 h
= CreateFileW (filename
, GENERIC_READ
, FILE_SHARE_READ
,
203 NULL
, OPEN_EXISTING
, 0, NULL
);
206 ReadFile (h
, buf
, sizeof (buf
), &n
, 0);
208 char *p
= (char *) memmem (buf
, n
, "PE\0\0", 4);
209 if (p
&& p
+ id_offset
<= buf
+ n
)
210 return p
[id_offset
] == '\003'; /* 02: GUI, 03: console */
216 iscmd (const char *argv0
, const char *what
)
219 n
= strlen (argv0
) - strlen (what
);
220 if (n
>= 2 && argv0
[1] != ':')
222 return n
>= 0 && strcasematch (argv0
+ n
, what
) &&
223 (n
== 0 || isdirsep (argv0
[n
- 1]));
226 #define ILLEGAL_SIG_FUNC_PTR ((_sig_func_ptr) (-2))
227 struct system_call_handle
229 _sig_func_ptr oldint
;
230 _sig_func_ptr oldquit
;
232 bool is_system_call ()
234 return oldint
!= ILLEGAL_SIG_FUNC_PTR
;
236 system_call_handle (bool issystem
)
239 oldint
= ILLEGAL_SIG_FUNC_PTR
;
242 sig_send (NULL
, __SIGHOLD
);
248 if (is_system_call ())
250 sigset_t child_block
;
251 oldint
= signal (SIGINT
, SIG_IGN
);
252 oldquit
= signal (SIGQUIT
, SIG_IGN
);
253 sigemptyset (&child_block
);
254 sigaddset (&child_block
, SIGCHLD
);
255 sigprocmask (SIG_BLOCK
, &child_block
, &oldmask
);
256 sig_send (NULL
, __SIGNOHOLD
);
259 ~system_call_handle ()
261 if (is_system_call ())
263 signal (SIGINT
, oldint
);
264 signal (SIGQUIT
, oldquit
);
265 sigprocmask (SIG_SETMASK
, &oldmask
, NULL
);
271 child_info_spawn NO_COPY ch_spawn
;
273 extern "C" void __posix_spawn_sem_release (void *sem
, int error
);
275 extern DWORD mutex_timeout
; /* defined in fhandler_termios.cc */
278 child_info_spawn::worker (const char *prog_arg
, const char *const *argv
,
279 const char *const envp
[], int mode
,
280 int in__stdin
, int in__stdout
)
286 /* Search for CTTY and retrieve its PGID */
287 cygheap_fdenum
cfd (false);
288 while (cfd
.next () >= 0)
289 if (cfd
->get_major () == DEV_PTYS_MAJOR
||
290 cfd
->get_major () == DEV_CONS_MAJOR
)
292 fhandler_termios
*fh
= (fhandler_termios
*) (fhandler_base
*) cfd
;
293 if (fh
->tc ()->ntty
== myself
->ctty
)
295 ctty_pgid
= fh
->tc ()->getpgid ();
300 /* Check if we have been called from exec{lv}p or spawn{lv}p and mask
301 mode to keep only the spawn mode. */
302 bool p_type_exec
= !!(mode
& _P_PATH_TYPE_EXEC
);
303 mode
= _P_MODE (mode
);
305 if (prog_arg
== NULL
)
307 syscall_printf ("prog_arg is NULL");
308 set_errno (EFAULT
); /* As on Linux. */
313 syscall_printf ("prog_arg is empty");
314 set_errno (ENOENT
); /* Per POSIX */
318 syscall_printf ("mode = %d, prog_arg = %.9500s", mode
, prog_arg
);
320 /* FIXME: This is no error condition on Linux. */
323 syscall_printf ("argv is NULL");
330 PWCHAR envblock
= NULL
;
332 bool reset_sendsig
= false;
335 PWCHAR runpath
= tp
.w_get ();
338 bool null_app_name
= false;
339 STARTUPINFOW si
= {};
342 system_call_handle
system_call (mode
== _P_SYSTEM
);
346 child_info_types chtype
;
347 if (mode
== _P_OVERLAY
)
352 moreinfo
= cygheap_exec_info::alloc ();
354 /* CreateProcess takes one long string that is the command line (sigh).
355 We need to quote any argument that has whitespace or embedded "'s. */
358 for (ac
= 0; argv
[ac
]; ac
++)
363 if ((ext
= perhaps_suffix (prog_arg
, real_path
, err
, FE_NADA
)) == NULL
)
370 res
= newargv
.setup (prog_arg
, real_path
, ext
, ac
, argv
, p_type_exec
);
375 if (!real_path
.iscygexec () && ::cygheap
->cwd
.get_error ())
377 small_printf ("Error: Current working directory %s.\n"
378 "Can't start native Windows application from here.\n\n",
379 ::cygheap
->cwd
.get_error_desc ());
380 set_errno (::cygheap
->cwd
.get_error ());
385 if (ac
== 3 && argv
[1][0] == '/' && tolower (argv
[1][1]) == 'c' &&
386 (iscmd (argv
[0], "command.com") || iscmd (argv
[0], "cmd.exe")))
388 real_path
.check (prog_arg
);
390 if (!real_path
.error
)
391 cmd
.add (real_path
.get_win32 ());
399 real_path
.set_path (argv
[0]);
400 null_app_name
= true;
404 if (real_path
.iscygexec ())
406 moreinfo
->argc
= newargv
.argc
;
407 moreinfo
->argv
= newargv
;
409 if ((wincmdln
|| !real_path
.iscygexec ())
410 && !cmd
.fromargv (newargv
, real_path
.get_win32 (),
411 real_path
.iscygexec ()))
418 if (mode
!= _P_OVERLAY
|| !real_path
.iscygexec ()
419 || !DuplicateHandle (GetCurrentProcess (), myself
.shared_handle (),
420 GetCurrentProcess (), &moreinfo
->myself_pinfo
,
421 0, TRUE
, DUPLICATE_SAME_ACCESS
))
422 moreinfo
->myself_pinfo
= NULL
;
424 VerifyHandle (moreinfo
->myself_pinfo
);
427 PROCESS_INFORMATION pi
;
428 pi
.hProcess
= pi
.hThread
= NULL
;
429 pi
.dwProcessId
= pi
.dwThreadId
= 0;
431 c_flags
= GetPriorityClass (GetCurrentProcess ());
432 sigproc_printf ("priority class %d", c_flags
);
434 c_flags
|= CREATE_SEPARATE_WOW_VDM
| CREATE_UNICODE_ENVIRONMENT
;
436 /* Add CREATE_DEFAULT_ERROR_MODE flag for non-Cygwin processes so they
437 get the default error mode instead of inheriting the mode Cygwin
438 uses. This allows things like Windows Error Reporting/JIT debugging
439 to work with processes launched from a Cygwin shell. */
440 if (!real_path
.iscygexec ())
441 c_flags
|= CREATE_DEFAULT_ERROR_MODE
;
443 /* We're adding the CREATE_BREAKAWAY_FROM_JOB flag here to workaround
444 issues with the "Program Compatibility Assistant (PCA) Service".
445 For some reason, when starting long running sessions from mintty(*),
446 the affected svchost.exe process takes more and more memory and at one
447 point takes over the CPU. At this point the machine becomes
448 unresponsive. The only way to get back to normal is to stop the
449 entire mintty session, or to stop the PCA service. However, a process
450 which is controlled by PCA is part of a compatibility job, which
451 allows child processes to break away from the job. This helps to
454 First we call IsProcessInJob. It fetches the information whether or
455 not we're part of a job 20 times faster than QueryInformationJobObject.
457 (*) Note that this is not mintty's fault. It has just been observed
458 with mintty in the first place. See the archives for more info:
459 http://cygwin.com/ml/cygwin-developers/2012-02/msg00018.html */
460 JOBOBJECT_BASIC_LIMIT_INFORMATION jobinfo
;
463 if (IsProcessInJob (GetCurrentProcess (), NULL
, &is_in_job
)
465 && QueryInformationJobObject (NULL
, JobObjectBasicLimitInformation
,
466 &jobinfo
, sizeof jobinfo
, NULL
)
467 && (jobinfo
.LimitFlags
& (JOB_OBJECT_LIMIT_BREAKAWAY_OK
468 | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
)))
470 debug_printf ("Add CREATE_BREAKAWAY_FROM_JOB");
471 c_flags
|= CREATE_BREAKAWAY_FROM_JOB
;
474 if (mode
== _P_DETACH
)
475 c_flags
|= DETACHED_PROCESS
;
477 fhandler_console::need_invisible ();
479 if (mode
!= _P_OVERLAY
)
480 myself
->exec_sendsig
= NULL
;
483 /* Reset sendsig so that any process which wants to send a signal
484 to this pid will wait for the new process to become active.
485 Save the old value in case the exec fails. */
486 if (!myself
->exec_sendsig
)
488 myself
->exec_sendsig
= myself
->sendsig
;
489 myself
->exec_dwProcessId
= myself
->dwProcessId
;
490 myself
->sendsig
= NULL
;
491 reset_sendsig
= true;
499 USHORT len
= real_path
.get_nt_native_path ()->Length
/ sizeof (WCHAR
);
500 if (RtlEqualUnicodePathPrefix (real_path
.get_nt_native_path (),
503 runpath
= real_path
.get_wide_win32_path (runpath
);
504 /* If the executable path length is < MAX_PATH, make sure the long
505 path win32 prefix is removed from the path to make subsequent
506 not long path aware native Win32 child processes happy. */
507 if (len
< MAX_PATH
+ 4)
509 if (runpath
[5] == ':')
511 else if (len
< MAX_PATH
+ 6)
512 *(runpath
+= 6) = L
'\\';
515 else if (len
< NT_MAX_PATH
- ro_u_globalroot
.Length
/ sizeof (WCHAR
))
517 UNICODE_STRING rpath
;
519 RtlInitEmptyUnicodeString (&rpath
, runpath
,
520 (NT_MAX_PATH
- 1) * sizeof (WCHAR
));
521 RtlCopyUnicodeString (&rpath
, &ro_u_globalroot
);
522 RtlAppendUnicodeStringToString (&rpath
,
523 real_path
.get_nt_native_path ());
527 set_errno (ENAMETOOLONG
);
533 cygbench ("spawn-worker");
535 if (!real_path
.iscygexec())
536 ::cygheap
->fdtab
.set_file_pointers_for_exec ();
538 /* If we switch the user, merge the user's Windows environment. */
539 bool switch_user
= ::cygheap
->user
.issetuid ()
540 && (::cygheap
->user
.saved_uid
541 != ::cygheap
->user
.real_uid
);
542 moreinfo
->envp
= build_env (envp
, envblock
, moreinfo
->envc
,
543 real_path
.iscygexec (),
544 switch_user
? ::cygheap
->user
.primary_token ()
546 if (!moreinfo
->envp
|| !envblock
)
552 set (chtype
, real_path
.iscygexec ());
554 __stdout
= in__stdout
;
557 si
.lpReserved2
= (LPBYTE
) this;
558 si
.cbReserved2
= sizeof (*this);
560 /* Depends on set call above.
561 Some file types might need extra effort in the parent after CreateProcess
562 and before copying the datastructures to the child. So we have to start
563 the child in suspend state, unfortunately, to avoid a race condition. */
564 if (!newargv
.win16_exe
565 && (!iscygwin () || mode
!= _P_OVERLAY
566 || ::cygheap
->fdtab
.need_fixup_before ()))
567 c_flags
|= CREATE_SUSPENDED
;
568 /* If a native application should be spawned, we test here if the spawning
569 process is running in a console and, if so, if it's a foreground or
570 background process. If it's a background process, we start the native
571 process with the CREATE_NEW_PROCESS_GROUP flag set. This lets the native
572 process ignore Ctrl-C by default. If we don't do that, pressing Ctrl-C
573 in a console will break native processes running in the background,
574 because the Ctrl-C event is sent to all processes in the console, unless
575 they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */
576 if (!iscygwin () && ctty_pgid
&& ctty_pgid
!= myself
->pgid
)
577 c_flags
|= CREATE_NEW_PROCESS_GROUP
;
580 if (c_flags
& CREATE_NEW_PROCESS_GROUP
)
581 myself
->process_state
|= PID_NEW_PG
;
583 if (mode
== _P_DETACH
)
585 else if (mode
!= _P_OVERLAY
|| !my_wr_proc_pipe
)
588 wr_proc_pipe
= my_wr_proc_pipe
;
590 /* Don't allow child to inherit these handles if it's not a Cygwin program.
591 wr_proc_pipe will be injected later. parent won't be used by the child
592 so there is no reason for the child to have it open as it can confuse
593 ps into thinking that children of windows processes are all part of
594 the same "execed" process.
595 FIXME: Someday, make it so that parent is never created when starting
596 non-Cygwin processes. */
599 SetHandleInformation (wr_proc_pipe
, HANDLE_FLAG_INHERIT
, 0);
600 SetHandleInformation (parent
, HANDLE_FLAG_INHERIT
, 0);
603 if (mode
!= _P_OVERLAY
)
604 SetHandleInformation (my_wr_proc_pipe
, HANDLE_FLAG_INHERIT
, 0);
605 parent_winpid
= GetCurrentProcessId ();
607 PSECURITY_ATTRIBUTES sa
= (PSECURITY_ATTRIBUTES
) tp
.w_get ();
608 if (!sec_user_nih (sa
, cygheap
->user
.sid (),
609 well_known_authenticated_users_sid
,
610 PROCESS_QUERY_LIMITED_INFORMATION
))
613 fhandler_pty_slave
*ptys_primary
= NULL
;
614 fhandler_console
*cons_native
= NULL
;
615 termios
*cons_ti
= NULL
;
616 pid_t cons_owner
= 0;
617 for (int i
= 0; i
< 3; i
++)
619 const int chk_order
[] = {1, 0, 2};
620 int fd
= chk_order
[i
];
621 fhandler_base
*fh
= ::cygheap
->fdtab
[fd
];
622 if (fh
&& fh
->get_major () == DEV_PTYS_MAJOR
)
624 fhandler_pty_slave
*ptys
= (fhandler_pty_slave
*) fh
;
625 if (ptys_primary
== NULL
)
628 else if (fh
&& fh
->get_major () == DEV_CONS_MAJOR
)
630 fhandler_console
*cons
= (fhandler_console
*) fh
;
633 if (cons_native
== NULL
)
636 cons_ti
= &((tty
*)cons
->tc ())->ti
;
637 cons_owner
= cons
->get_owner ();
639 tty::cons_mode conmode
=
640 (ctty_pgid
&& ctty_pgid
== myself
->pgid
) ?
641 tty::native
: tty::restore
;
643 fhandler_console::set_input_mode (conmode
,
644 cons_ti
, cons
->get_handle_set ());
645 else if (fd
== 1 || fd
== 2)
646 fhandler_console::set_output_mode (conmode
,
647 cons_ti
, cons
->get_handle_set ());
651 struct fhandler_console::handle_set_t cons_handle_set
= { 0, };
653 /* Console handles will be closed by close_all_files(),
654 therefore, duplicate them here */
655 cons_native
->get_duplicated_handle_set (&cons_handle_set
);
661 while ((fd
= cfd
.next ()) >= 0)
662 if (cfd
->get_major () == DEV_PTYS_MAJOR
)
664 fhandler_pty_slave
*ptys
=
665 (fhandler_pty_slave
*)(fhandler_base
*) cfd
;
666 ptys
->create_invisible_console ();
667 ptys
->setup_locale ();
669 else if (cfd
->get_dev () == FH_PIPEW
670 && (fd
== (in__stdout
< 0 ? 1 : in__stdout
) || fd
== 2))
672 fhandler_pipe
*pipe
= (fhandler_pipe
*)(fhandler_base
*) cfd
;
673 pipe
->close_query_handle ();
674 pipe
->set_pipe_non_blocking (false);
676 else if (cfd
->get_dev () == FH_PIPER
677 && fd
== (in__stdin
< 0 ? 0 : in__stdin
))
679 fhandler_pipe
*pipe
= (fhandler_pipe
*)(fhandler_base
*) cfd
;
680 pipe
->set_pipe_non_blocking (false);
684 bool enable_pcon
= false;
685 HANDLE ptys_from_master_nat
= NULL
;
686 HANDLE ptys_input_available_event
= NULL
;
687 HANDLE ptys_pcon_mutex
= NULL
;
688 HANDLE ptys_input_mutex
= NULL
;
689 tty
*ptys_ttyp
= NULL
;
690 bool stdin_is_ptys
= false;
691 if (!iscygwin () && ptys_primary
&& is_console_app (runpath
))
693 bool nopcon
= mode
!= _P_OVERLAY
&& mode
!= _P_WAIT
;
694 if (disable_pcon
|| !ptys_primary
->term_has_pcon_cap (envblock
))
696 ptys_ttyp
= ptys_primary
->get_ttyp ();
697 WaitForSingleObject (ptys_primary
->pcon_mutex
, INFINITE
);
698 if (ptys_primary
->setup_pseudoconsole (nopcon
))
700 ReleaseMutex (ptys_primary
->pcon_mutex
);
701 HANDLE h_stdin
= handle ((in__stdin
< 0 ? 0 : in__stdin
), false);
702 if (h_stdin
== ptys_primary
->get_handle_nat ())
703 stdin_is_ptys
= true;
704 ptys_from_master_nat
= ptys_primary
->get_handle_nat ();
705 DuplicateHandle (GetCurrentProcess (), ptys_from_master_nat
,
706 GetCurrentProcess (), &ptys_from_master_nat
,
707 0, 0, DUPLICATE_SAME_ACCESS
);
708 ptys_input_available_event
=
709 ptys_primary
->get_input_available_event ();
710 DuplicateHandle (GetCurrentProcess (), ptys_input_available_event
,
711 GetCurrentProcess (), &ptys_input_available_event
,
712 0, 0, DUPLICATE_SAME_ACCESS
);
713 DuplicateHandle (GetCurrentProcess (), ptys_primary
->pcon_mutex
,
714 GetCurrentProcess (), &ptys_pcon_mutex
,
715 0, 0, DUPLICATE_SAME_ACCESS
);
716 DuplicateHandle (GetCurrentProcess (), ptys_primary
->input_mutex
,
717 GetCurrentProcess (), &ptys_input_mutex
,
718 0, 0, DUPLICATE_SAME_ACCESS
);
719 if (!enable_pcon
&& ptys_ttyp
->getpgid () == myself
->pgid
721 && ptys_ttyp
->pcon_input_state_eq (tty::to_cyg
))
723 WaitForSingleObject (ptys_input_mutex
, mutex_timeout
);
724 fhandler_pty_slave::transfer_input (tty::to_nat
,
725 ptys_primary
->get_handle (),
726 ptys_ttyp
, ptys_input_available_event
);
727 ReleaseMutex (ptys_input_mutex
);
731 /* Set up needed handles for stdio */
732 si
.dwFlags
= STARTF_USESTDHANDLES
;
733 si
.hStdInput
= handle ((in__stdin
< 0 ? 0 : in__stdin
), false);
734 si
.hStdOutput
= handle ((in__stdout
< 0 ? 1 : in__stdout
), true);
735 si
.hStdError
= handle (2, true);
740 init_console_handler (myself
->ctty
> 0);
743 /* When ruid != euid we create the new process under the current original
744 account and impersonate in child, this way maintaining the different
745 effective vs. real ids.
746 FIXME: If ruid != euid and ruid != saved_uid we currently give
747 up on ruid. The new process will have ruid == euid. */
748 ::cygheap
->user
.deimpersonate ();
750 if (!real_path
.iscygexec () && mode
== _P_OVERLAY
)
751 myself
->process_state
|= PID_NOTCYGWIN
;
753 cygpid
= (mode
!= _P_OVERLAY
) ? create_cygwin_pid () : myself
->pid
;
755 wchar_t wcmd
[(size_t) cmd
];
756 if (!::cygheap
->user
.issetuid ()
757 || (::cygheap
->user
.saved_uid
== ::cygheap
->user
.real_uid
758 && ::cygheap
->user
.saved_gid
== ::cygheap
->user
.real_gid
759 && !::cygheap
->user
.groups
.issetgroups ()
760 && !::cygheap
->user
.setuid_to_restricted
))
762 rc
= CreateProcessW (runpath
, /* image name w/ full path */
763 cmd
.wcs (wcmd
), /* what was passed to exec */
764 sa
, /* process security attrs */
765 sa
, /* thread security attrs */
766 TRUE
, /* inherit handles */
768 envblock
, /* environment */
775 /* Give access to myself */
776 if (mode
== _P_OVERLAY
)
780 HWINSTA hwst_orig
= GetProcessWindowStation ();
782 HDESK hdsk_orig
= GetThreadDesktop (GetCurrentThreadId ());
783 /* Don't create WindowStation and Desktop for restricted child. */
784 if (!::cygheap
->user
.setuid_to_restricted
)
786 PSECURITY_ATTRIBUTES sa
;
788 WCHAR wstname
[1024] = { L
'\0' };
790 sa
= sec_user ((PSECURITY_ATTRIBUTES
) alloca (1024),
791 ::cygheap
->user
.sid ());
792 /* We're creating a window station per user, not per logon
793 session First of all we might not have a valid logon session
794 for the user (logon by create_token), and second, it doesn't
795 make sense in terms of security to create a new window
796 station for every logon of the same user. It just fills up
797 the system with window stations for no good reason. */
798 hwst
= CreateWindowStationW (::cygheap
->user
.get_windows_id (sid
),
799 0, GENERIC_READ
| GENERIC_WRITE
, sa
);
801 system_printf ("CreateWindowStation failed, %E");
802 else if (!SetProcessWindowStation (hwst
))
803 system_printf ("SetProcessWindowStation failed, %E");
804 else if (!(hdsk
= CreateDesktopW (L
"Default", NULL
, NULL
, 0,
806 system_printf ("CreateDesktop failed, %E");
809 wcpcpy (wcpcpy (wstname
, sid
), L
"\\Default");
810 si
.lpDesktop
= wstname
;
811 debug_printf ("Desktop: %W", si
.lpDesktop
);
815 rc
= CreateProcessAsUserW (::cygheap
->user
.primary_token (),
816 runpath
, /* image name w/ full path */
817 cmd
.wcs (wcmd
), /* what was passed to exec */
818 sa
, /* process security attrs */
819 sa
, /* thread security attrs */
820 TRUE
, /* inherit handles */
822 envblock
, /* environment */
828 SetProcessWindowStation (hwst_orig
);
829 CloseWindowStation (hwst
);
833 SetThreadDesktop (hdsk_orig
);
838 if (mode
!= _P_OVERLAY
)
839 SetHandleInformation (my_wr_proc_pipe
, HANDLE_FLAG_INHERIT
,
840 HANDLE_FLAG_INHERIT
);
842 /* Set errno now so that debugging messages from it appear before our
843 final debugging message [this is a general rule for debugging
848 syscall_printf ("CreateProcess failed, %E");
849 /* If this was a failed exec, restore the saved sendsig. */
852 myself
->sendsig
= myself
->exec_sendsig
;
853 myself
->exec_sendsig
= NULL
;
855 myself
->process_state
&= ~PID_NOTCYGWIN
;
856 /* Reset handle inheritance to default when the execution of a'
857 non-Cygwin process fails. Only need to do this for _P_OVERLAY
858 since the handle will be closed otherwise. Don't need to do
859 this for 'parent' since it will be closed in every case.
861 if (!iscygwin () && mode
== _P_OVERLAY
)
862 SetHandleInformation (wr_proc_pipe
, HANDLE_FLAG_INHERIT
,
863 HANDLE_FLAG_INHERIT
);
864 if (wr_proc_pipe
== my_wr_proc_pipe
)
865 wr_proc_pipe
= NULL
; /* We still own it: don't nuke in destructor */
867 /* Restore impersonation. In case of _P_OVERLAY this isn't
868 allowed since it would overwrite child data. */
869 if (mode
!= _P_OVERLAY
)
870 ::cygheap
->user
.reimpersonate ();
876 /* The CREATE_SUSPENDED case is handled below */
877 if (iscygwin () && !(c_flags
& CREATE_SUSPENDED
))
878 strace
.write_childpid (pi
.dwProcessId
);
880 /* Fixup the parent data structures if needed and resume the child's
882 if (::cygheap
->fdtab
.need_fixup_before ())
883 ::cygheap
->fdtab
.fixup_before_exec (pi
.dwProcessId
);
885 /* Print the original program name here so the user can see that too. */
886 syscall_printf ("pid %d, prog_arg %s, cmd line %.9500s)",
887 rc
? cygpid
: (unsigned int) -1, prog_arg
, (const char *) cmd
);
889 /* Name the handle similarly to proc_subproc. */
890 ProtectHandle1 (pi
.hProcess
, childhProc
);
892 if (mode
== _P_OVERLAY
)
894 myself
->dwProcessId
= pi
.dwProcessId
;
896 myself
.hProcess
= hExeced
= pi
.hProcess
;
897 HANDLE old_winpid_hdl
= myself
.shared_winpid_handle ();
898 if (!real_path
.iscygexec ())
900 /* If the child process is not a Cygwin process, we have to
901 create a new winpid symlink on behalf of the child process
902 not being able to do this by itself. */
903 myself
.create_winpid_symlink ();
905 NtClose (old_winpid_hdl
);
906 real_path
.get_wide_win32_path (myself
->progname
); // FIXME: race?
907 sigproc_printf ("new process name %W", myself
->progname
);
913 myself
->set_has_pgid_children ();
914 ProtectHandle (pi
.hThread
);
916 PID_IN_USE
| (real_path
.iscygexec () ? 0 : PID_NOTCYGWIN
));
919 syscall_printf ("pinfo failed");
920 if (get_errno () != ENOMEM
)
925 child
->dwProcessId
= pi
.dwProcessId
;
926 child
.hProcess
= pi
.hProcess
;
928 real_path
.get_wide_win32_path (child
->progname
);
929 /* This introduces an unreferenced, open handle into the child.
930 The purpose is to keep the pid shared memory open so that all
931 of the fields filled out by child.remember do not disappear
932 and so there is not a brief period during which the pid is
934 DuplicateHandle (GetCurrentProcess (), child
.shared_handle (),
935 pi
.hProcess
, NULL
, 0, 0, DUPLICATE_SAME_ACCESS
);
936 if (!real_path
.iscygexec ())
938 /* If the child process is not a Cygwin process, we have to
939 create a new winpid symlink and induce it into the child
940 process as well to keep it over the lifetime of the child. */
941 child
.create_winpid_symlink ();
942 DuplicateHandle (GetCurrentProcess (),
943 child
.shared_winpid_handle (),
944 pi
.hProcess
, NULL
, 0, 0, DUPLICATE_SAME_ACCESS
);
946 child
->start_time
= time (NULL
); /* Register child's starting time. */
947 child
->nice
= myself
->nice
;
949 if (mode
!= _P_DETACH
950 && (!child
.remember () || !child
.attach ()))
952 /* FIXME: Child in strange state now */
953 CloseHandle (pi
.hProcess
);
954 ForceCloseHandle (pi
.hThread
);
960 /* Start the child running */
961 if (c_flags
& CREATE_SUSPENDED
)
963 /* Inject a non-inheritable wr_proc_pipe handle into child so that we
964 can accurately track when the child exits without keeping this
965 process waiting around for it to exit. */
967 DuplicateHandle (GetCurrentProcess (), wr_proc_pipe
, pi
.hProcess
, NULL
,
968 0, false, DUPLICATE_SAME_ACCESS
);
969 ResumeThread (pi
.hThread
);
971 strace
.write_childpid (pi
.dwProcessId
);
973 ForceCloseHandle (pi
.hThread
);
975 sigproc_printf ("spawned windows pid %d", pi
.dwProcessId
);
978 if ((mode
== _P_DETACH
|| mode
== _P_NOWAIT
) && !iscygwin ())
981 /* Just mark a non-cygwin process as 'synced'. We will still eventually
982 wait for it to exit in maybe_set_exit_code_from_windows(). */
983 synced
= iscygwin () ? sync (pi
.dwProcessId
, pi
.hProcess
, INFINITE
) : true;
988 myself
.hProcess
= pi
.hProcess
;
991 if (!proc_retry (pi
.hProcess
))
996 close_all_files (true);
1001 close_all_files (true);
1002 if (!my_wr_proc_pipe
1003 && WaitForSingleObject (pi
.hProcess
, 0) == WAIT_TIMEOUT
)
1007 __posix_spawn_sem_release (sem
, 0);
1008 if (enable_pcon
|| ptys_ttyp
|| cons_native
)
1009 WaitForSingleObject (pi
.hProcess
, INFINITE
);
1012 ptys_ttyp
->wait_pcon_fwd ();
1013 if (ptys_ttyp
->getpgid () == myself
->pgid
&& stdin_is_ptys
1014 && ptys_ttyp
->pcon_input_state_eq (tty::to_nat
))
1016 WaitForSingleObject (ptys_input_mutex
, mutex_timeout
);
1017 fhandler_pty_slave::transfer_input (tty::to_cyg
,
1018 ptys_from_master_nat
, ptys_ttyp
,
1019 ptys_input_available_event
);
1020 ReleaseMutex (ptys_input_mutex
);
1022 CloseHandle (ptys_from_master_nat
);
1023 CloseHandle (ptys_input_mutex
);
1024 CloseHandle (ptys_input_available_event
);
1025 WaitForSingleObject (ptys_pcon_mutex
, INFINITE
);
1026 fhandler_pty_slave::close_pseudoconsole (ptys_ttyp
);
1027 ReleaseMutex (ptys_pcon_mutex
);
1028 CloseHandle (ptys_pcon_mutex
);
1032 tty::cons_mode conmode
=
1033 cons_owner
== myself
->pid
? tty::restore
: tty::cygwin
;
1034 fhandler_console::set_output_mode (conmode
, cons_ti
,
1036 fhandler_console::set_input_mode (conmode
, cons_ti
,
1038 fhandler_console::close_handle_set (&cons_handle_set
);
1040 myself
.exit (EXITCODE_NOSET
);
1045 if (waitpid (cygpid
, &res
, 0) != cygpid
)
1049 ptys_ttyp
->wait_pcon_fwd ();
1050 if (ptys_ttyp
->getpgid () == myself
->pgid
&& stdin_is_ptys
1051 && ptys_ttyp
->pcon_input_state_eq (tty::to_nat
))
1053 WaitForSingleObject (ptys_input_mutex
, mutex_timeout
);
1054 fhandler_pty_slave::transfer_input (tty::to_cyg
,
1055 ptys_from_master_nat
, ptys_ttyp
,
1056 ptys_input_available_event
);
1057 ReleaseMutex (ptys_input_mutex
);
1059 CloseHandle (ptys_from_master_nat
);
1060 CloseHandle (ptys_input_mutex
);
1061 CloseHandle (ptys_input_available_event
);
1062 WaitForSingleObject (ptys_pcon_mutex
, INFINITE
);
1063 fhandler_pty_slave::close_pseudoconsole (ptys_ttyp
);
1064 ReleaseMutex (ptys_pcon_mutex
);
1065 CloseHandle (ptys_pcon_mutex
);
1069 tty::cons_mode conmode
=
1070 cons_owner
== myself
->pid
? tty::restore
: tty::cygwin
;
1071 fhandler_console::set_output_mode (conmode
, cons_ti
,
1073 fhandler_console::set_input_mode (conmode
, cons_ti
,
1075 fhandler_console::close_handle_set (&cons_handle_set
);
1079 res
= 0; /* Lost all memory of this child. */
1092 if (get_errno () == ENOMEM
)
1107 cwait (int *result
, int pid
, int)
1109 return waitpid (pid
, result
, 0);
1113 * Helper function for spawn runtime calls.
1114 * Doesn't search the path.
1118 spawnve (int mode
, const char *path
, const char *const *argv
,
1119 const char *const *envp
)
1121 static char *const empty_env
[] = { NULL
};
1125 syscall_printf ("spawnve (%s, %s, %p)", path
, argv
[0], envp
);
1130 switch (_P_MODE (mode
))
1133 ch_spawn
.worker (path
, argv
, envp
, mode
);
1134 /* Errno should be set by worker. */
1143 ret
= ch_spawn
.worker (path
, argv
, envp
, mode
);
1154 * spawn functions as implemented in the MS runtime library.
1155 * Most of these based on (and copied from) newlib/libc/posix/execXX.c
1159 spawnl (int mode
, const char *path
, const char *arg0
, ...)
1163 const char *argv
[256];
1165 va_start (args
, arg0
);
1170 argv
[i
] = va_arg (args
, const char *);
1171 while (argv
[i
++] != NULL
);
1175 return spawnve (mode
, path
, (char * const *) argv
, cur_environ ());
1179 spawnle (int mode
, const char *path
, const char *arg0
, ...)
1183 const char * const *envp
;
1184 const char *argv
[256];
1186 va_start (args
, arg0
);
1191 argv
[i
] = va_arg (args
, const char *);
1192 while (argv
[i
++] != NULL
);
1194 envp
= va_arg (args
, const char * const *);
1197 return spawnve (mode
, path
, (char * const *) argv
, (char * const *) envp
);
1201 spawnlp (int mode
, const char *file
, const char *arg0
, ...)
1205 const char *argv
[256];
1208 va_start (args
, arg0
);
1213 argv
[i
] = va_arg (args
, const char *);
1214 while (argv
[i
++] != NULL
);
1218 return spawnve (mode
| _P_PATH_TYPE_EXEC
, find_exec (file
, buf
),
1219 (char * const *) argv
, cur_environ ());
1223 spawnlpe (int mode
, const char *file
, const char *arg0
, ...)
1227 const char * const *envp
;
1228 const char *argv
[256];
1231 va_start (args
, arg0
);
1236 argv
[i
] = va_arg (args
, const char *);
1237 while (argv
[i
++] != NULL
);
1239 envp
= va_arg (args
, const char * const *);
1242 return spawnve (mode
| _P_PATH_TYPE_EXEC
, find_exec (file
, buf
),
1243 (char * const *) argv
, envp
);
1247 spawnv (int mode
, const char *path
, const char * const *argv
)
1249 return spawnve (mode
, path
, argv
, cur_environ ());
1253 spawnvp (int mode
, const char *file
, const char * const *argv
)
1256 return spawnve (mode
| _P_PATH_TYPE_EXEC
,
1257 find_exec (file
, buf
, "PATH", FE_NNF
) ?: "",
1258 argv
, cur_environ ());
1262 spawnvpe (int mode
, const char *file
, const char * const *argv
,
1263 const char * const *envp
)
1266 return spawnve (mode
| _P_PATH_TYPE_EXEC
,
1267 find_exec (file
, buf
, "PATH", FE_NNF
) ?: "",
1272 av::setup (const char *prog_arg
, path_conv
& real_path
, const char *ext
,
1273 int argc
, const char *const *argv
, bool p_type_exec
)
1276 bool exeext
= ascii_strcasematch (ext
, ".exe");
1277 new (this) av (argc
, argv
);
1278 if ((exeext
&& real_path
.iscygexec ()) || ascii_strcasematch (ext
, ".bat")
1279 || (!*ext
&& ((p
= ext
- 4) > real_path
.get_win32 ())
1280 && (ascii_strcasematch (p
, ".bat") || ascii_strcasematch (p
, ".cmd")
1281 || ascii_strcasematch (p
, ".btm"))))
1282 /* no extra checks needed */;
1289 OBJECT_ATTRIBUTES attr
;
1295 status
= NtOpenFile (&h
, SYNCHRONIZE
| GENERIC_READ
,
1296 real_path
.get_object_attr (attr
, sec_none_nih
),
1297 &io
, FILE_SHARE_VALID_FLAGS
,
1298 FILE_SYNCHRONOUS_IO_NONALERT
1299 | FILE_OPEN_FOR_BACKUP_INTENT
1300 | FILE_NON_DIRECTORY_FILE
);
1301 if (status
== STATUS_IO_REPARSE_TAG_NOT_HANDLED
)
1303 /* This is most likely an app execution alias (such as the
1304 Windows Store version of Python, i.e. not a Cygwin program */
1305 real_path
.set_cygexec (false);
1308 if (!NT_SUCCESS (status
))
1310 /* File is not readable? Doesn't mean it's not executable.
1311 Test for executability and if so, just assume the file is
1312 a cygwin executable and go ahead. */
1313 if (status
== STATUS_ACCESS_DENIED
&& real_path
.has_acls ()
1314 && check_file_access (real_path
, X_OK
, true) == 0)
1316 real_path
.set_cygexec (true);
1319 SetLastError (RtlNtStatusToDosError (status
));
1322 if (!GetFileSizeEx (h
, &size
))
1327 if (size
.QuadPart
> (LONGLONG
) wincap
.allocation_granularity ())
1328 size
.LowPart
= wincap
.allocation_granularity ();
1330 HANDLE hm
= CreateFileMapping (h
, &sec_none_nih
, PAGE_READONLY
,
1335 /* ERROR_FILE_INVALID indicates very likely an empty file. */
1336 if (GetLastError () == ERROR_FILE_INVALID
)
1338 debug_printf ("zero length file, treat as script.");
1343 /* Try to map the first 64K of the image. That's enough for the local
1344 tests, and it's enough for hook_or_detect_cygwin to compute the IAT
1346 buf
= (char *) MapViewOfFile (hm
, FILE_MAP_READ
, 0, 0, size
.LowPart
);
1356 if (buf
[0] == 'M' && buf
[1] == 'Z')
1359 unsigned off
= (unsigned char) buf
[0x18] | (((unsigned char) buf
[0x19]) << 8);
1360 win16_exe
= off
< sizeof (IMAGE_DOS_HEADER
);
1362 real_path
.set_cygexec (hook_or_detect_cygwin (buf
, NULL
,
1365 real_path
.set_cygexec (false);
1366 UnmapViewOfFile (buf
);
1373 UnmapViewOfFile (buf
);
1375 real_path
.set_cygexec (false);
1382 debug_printf ("%s is possibly a script", real_path
.get_win32 ());
1385 if (*ptr
++ == '#' && *ptr
++ == '!')
1387 ptr
+= strspn (ptr
, " \t");
1388 size_t len
= strcspn (ptr
, "\r\n");
1389 while (ptr
[len
- 1] == ' ' || ptr
[len
- 1] == '\t')
1393 char *namebuf
= (char *) alloca (len
+ 1);
1394 memcpy (namebuf
, ptr
, len
);
1395 namebuf
[len
] = '\0';
1396 for (ptr
= pgm
= namebuf
; *ptr
; ptr
++)
1397 if (!arg1
&& (*ptr
== ' ' || *ptr
== '\t'))
1399 /* Null terminate the initial command and step over any
1400 additional white space. If we've hit the end of the
1401 line, exit the loop. Otherwise, we've found the first
1402 argument. Position the current pointer on the last known
1405 char *newptr
= ptr
+ 1;
1406 newptr
+= strspn (newptr
, " \t");
1414 UnmapViewOfFile (buf
);
1416 /* Check if script is executable. Otherwise we start non-executable
1417 scripts successfully, which is incorrect behaviour. */
1418 if (real_path
.has_acls ()
1419 && check_file_access (real_path
, X_OK
, true) < 0)
1420 return -1; /* errno is already set. */
1426 /* Not called from exec[lv]p. Don't try to treat as script. */
1427 debug_printf ("%s is not a valid executable",
1428 real_path
.get_win32 ());
1429 set_errno (ENOEXEC
);
1432 if (ascii_strcasematch (ext
, ".com"))
1434 pgm
= (char *) "/bin/sh";
1438 /* Replace argv[0] with the full path to the script if this is the
1439 first time through the loop. */
1440 replace0_maybe (prog_arg
);
1443 * pgm interpreter name
1444 * arg1 optional string
1449 find_exec (pgm
, real_path
, "PATH", FE_NADA
, &ext
);
1450 unshift (real_path
.get_posix ());
1452 if (real_path
.iscygexec ())
1461 /* The following __posix_spawn_* functions are called from newlib's posix_spawn
1462 implementation. The original code in newlib has been taken from FreeBSD,
1463 and the core code relies on specific, non-portable behaviour of vfork(2).
1464 Our replacement implementation uses a semaphore to synchronize parent and
1465 child process. Note: __posix_spawn_fork in fork.cc is part of the set. */
1467 /* Create an inheritable semaphore. Set it to 0 (== non-signalled), so the
1468 parent can wait on the semaphore immediately. */
1470 __posix_spawn_sem_create (void **semp
)
1473 OBJECT_ATTRIBUTES attr
;
1478 InitializeObjectAttributes (&attr
, NULL
, OBJ_INHERIT
, NULL
, NULL
);
1479 status
= NtCreateSemaphore (&sem
, SEMAPHORE_ALL_ACCESS
, &attr
, 0, INT_MAX
);
1480 if (!NT_SUCCESS (status
))
1481 return geterrno_from_nt_status (status
);
1486 /* Signal the semaphore. "error" should be 0 if all went fine and the
1487 exec'd child process is up and running, a useful POSIX error code otherwise.
1488 After releasing the semaphore, the value of the semaphore reflects
1489 the error code + 1. Thus, after WFMO in__posix_spawn_sem_wait_and_close,
1490 querying the value of the semaphore returns either 0 if all went well,
1491 or a value > 0 equivalent to the POSIX error code. */
1493 __posix_spawn_sem_release (void *sem
, int error
)
1495 ReleaseSemaphore (sem
, error
+ 1, NULL
);
1498 /* Helper to check the semaphore value. */
1500 __posix_spawn_sem_query (void *sem
)
1502 SEMAPHORE_BASIC_INFORMATION sbi
;
1504 NtQuerySemaphore (sem
, SemaphoreBasicInformation
, &sbi
, sizeof sbi
, NULL
);
1505 return sbi
.CurrentCount
;
1508 /* Called from parent to wait for fork/exec completion. We're waiting for
1509 the semaphore as well as the child's process handle, so even if the
1510 child crashes without signalling the semaphore, we won't wait infinitely. */
1512 __posix_spawn_sem_wait_and_close (void *sem
, void *proc
)
1515 HANDLE w4
[2] = { sem
, proc
};
1517 switch (WaitForMultipleObjects (2, w4
, FALSE
, INFINITE
))
1520 ret
= __posix_spawn_sem_query (sem
);
1522 case WAIT_OBJECT_0
+ 1:
1523 /* If we return here due to the child process dying, the semaphore is
1524 very likely not signalled. Check this here and return a valid error
1526 ret
= __posix_spawn_sem_query (sem
);
1531 ret
= geterrno_from_win_error ();
1539 /* Replacement for execve/execvpe, called from forked child in newlib's
1540 posix_spawn. The relevant difference is the additional semaphore
1541 so the worker method (which is not supposed to return on success)
1542 can signal the semaphore after sync'ing with the exec'd child. */
1544 __posix_spawn_execvpe (const char *path
, char * const *argv
, char *const *envp
,
1545 HANDLE sem
, int use_env_path
)
1549 static char *const empty_env
[] = { NULL
};
1552 ch_spawn
.set_sem (sem
);
1553 ch_spawn
.worker (use_env_path
? (find_exec (path
, buf
, "PATH", FE_NNF
) ?: "")
1556 _P_OVERLAY
| (use_env_path
? _P_PATH_TYPE_EXEC
: 0));
1557 __posix_spawn_sem_release (sem
, errno
);