From c16548b2a222c8ab43ae35651d069af4191836c6 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 11 Dec 2006 18:55:29 +0000 Subject: [PATCH] * child_info.h (child_info_spawn::__stdin): New element. (child_info_spawn::__stdin): Ditto. (CURR_CHILD_INFO_MAGIC): Regenerate. * dcrt0.cc (check_sanity_and_sync): Minor cleanup. (child_info_spawn::handle_spawn): Handle new __std* elements by calling move_fd. * dtable.cc (dtable::move_fd): Define new function. * dtable.h (dtable::move_fd): Declare new function. * fhandler.h (fhandler_pipe::popen_pid): Declare new element. * fhandler.h (fhandler_pipe::get_popen_pid): Define new function. * fhandler.h (fhandler_pipe::set_popen_pid): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Zero popen_pid. (fhandler_pipe::dup): Ditto. * spawn.cc (handle): Change second argument to bool. (spawn_guts): Accept __stdin/__stdout arguments and set them appropriately in child_info structure and in STARTUPINFO structure. * syscalls.cc (popen): New cygwin-specific implementation using spawn. (pclose): Ditto. * winsup.h (spawn_guts): Accommodate new arguments for spawn_guts. * fhandler.cc (fhandler_base::set_no_inheritance): Make second arg a bool. * fhandler.h (fhandler_base::set_no_inheritance): Ditto for declaration. * child_info.h (child_info::msv_count): Rename from the now-inappropriate "zero". (child_info_spawn::filler): Add filler to work around Vista bug. (child_info_fork::filler): Ditto. * dcrt0.cc (get_cygwin_startup_info): Remove "zero" check since it is now always filled out. * fork.cc (frok::parent): Move ch.zero manipulation to constructor. * spawn.cc (spawn_guts): Ditto. Remove _ch wrapper. * sigproc.cc (child_info::child_info): Initialize starter[]. * shared.cc (shared_info::heap_slop_size): Remove noisy system_printfs. * shared_info.h (CURR_SHARED_MAGIC): Regenerate. --- winsup/cygwin/ChangeLog | 104 ++++++++++++++++++++++++----------- winsup/cygwin/child_info.h | 9 ++- winsup/cygwin/dcrt0.cc | 42 +++----------- winsup/cygwin/dtable.cc | 8 +++ winsup/cygwin/dtable.h | 1 + winsup/cygwin/fhandler.cc | 28 ++++++---- winsup/cygwin/fhandler.h | 16 ++++-- winsup/cygwin/fork.cc | 4 -- winsup/cygwin/pipe.cc | 3 +- winsup/cygwin/shared.cc | 6 -- winsup/cygwin/shared_info.h | 2 +- winsup/cygwin/sigproc.cc | 3 + winsup/cygwin/spawn.cc | 36 ++++++------ winsup/cygwin/syscalls.cc | 107 ++++++++++++++++++++++++++++++++++++ winsup/cygwin/winsup.h | 3 + 15 files changed, 251 insertions(+), 121 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index a20dfb6bc..05071df0b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,41 @@ +2006-12-11 Christopher Faylor + + * child_info.h (child_info_spawn::__stdin): New element. + (child_info_spawn::__stdin): Ditto. + (CURR_CHILD_INFO_MAGIC): Regenerate. + * dcrt0.cc (check_sanity_and_sync): Minor cleanup. + (child_info_spawn::handle_spawn): Handle new __std* elements by calling + move_fd. + * dtable.cc (dtable::move_fd): Define new function. + * dtable.h (dtable::move_fd): Declare new function. + * fhandler.h (fhandler_pipe::popen_pid): Declare new element. + * fhandler.h (fhandler_pipe::get_popen_pid): Define new function. + * fhandler.h (fhandler_pipe::set_popen_pid): Ditto. + * pipe.cc (fhandler_pipe::fhandler_pipe): Zero popen_pid. + (fhandler_pipe::dup): Ditto. + * spawn.cc (handle): Change second argument to bool. + (spawn_guts): Accept __stdin/__stdout arguments and set them + appropriately in child_info structure and in STARTUPINFO structure. + * syscalls.cc (popen): New cygwin-specific implementation using spawn. + (pclose): Ditto. + * winsup.h (spawn_guts): Accommodate new arguments for spawn_guts. + + * fhandler.cc (fhandler_base::set_no_inheritance): Make second arg a bool. + * fhandler.h (fhandler_base::set_no_inheritance): Ditto for declaration. + + * child_info.h (child_info::msv_count): Rename from the now-inappropriate + "zero". + (child_info_spawn::filler): Add filler to work around Vista bug. + (child_info_fork::filler): Ditto. + * dcrt0.cc (get_cygwin_startup_info): Remove "zero" check since it is + now always filled out. + * fork.cc (frok::parent): Move ch.zero manipulation to constructor. + * spawn.cc (spawn_guts): Ditto. Remove _ch wrapper. + * sigproc.cc (child_info::child_info): Initialize starter[]. + + * shared.cc (shared_info::heap_slop_size): Remove noisy system_printfs. + * shared_info.h (CURR_SHARED_MAGIC): Regenerate. + 2006-12-11 Corinna Vinschen * fhandler.cc (rootdir): Fix typo in comment. @@ -78,7 +116,7 @@ 2006-12-06 Corinna Vinschen - * termios.cc: Change include order to accomodate change to sys/ioctl.h. + * termios.cc: Change include order to accommodate change to sys/ioctl.h. 2006-12-06 Corinna Vinschen @@ -123,7 +161,7 @@ * fork.cc (frok::parent): Set ch.zero[0] to a sensible count value if wincap.needs_count_in_si_lpres2 is set. * spawn.cc (spawn_guts): Ditto. Add filler bytes after ch on stack - to accomodate needs_count_in_si_lpres2. + to accommodate needs_count_in_si_lpres2. * wincap.h: Define needs_count_in_si_lpres2 throughout. * wincap.cc: Ditto. @@ -153,7 +191,7 @@ * security.cc (create_token): Revert erroneous change to test subauth_token for INVAILD_HANDLE_VALUE. - * syscalls.cc (seteuid32): Set create_token's subauth_token parameter + * syscalls.cc (seteuid32): Set create_token's subauth_token parameter back to NULL. 2006-11-28 Corinna Vinschen @@ -175,7 +213,7 @@ * cyglsa.h: New header file. * environ.cc: Disable subauth settings. - * grp.cc: Accomodate cygsidlist's count now being a method. + * grp.cc: Accommodate cygsidlist's count now being a method. * sec_helper.cc (SECURITY_MANDATORY_INTEGRITY_AUTHORITY): Remove. (mandatory_medium_integrity_sid): Remove. (mandatory_high_integrity_sid): Remove. @@ -189,7 +227,7 @@ (cygsidlist::add): Move here from security.h. Add well_known parameter. Set well_known_sid accordingly. Don't allow duplicate SIDs. * security.cc: Include cyglsa.h and cygwin/version.h. Throughout - accomodate cygsidlist's count now being a method. Throughout drop + accommodate cygsidlist's count now being a method. Throughout drop redundant "contains" tests. (get_user_local_groups): Add local groups as well known SIDs. (get_token_group_sidlist): Add well known groups as well known SIDs. @@ -201,11 +239,11 @@ (get_system_priv_list): Make static. Return size of TOKEN_PRIVILEGES structure. (get_priv_list): Ditto. - (create_token): Accomodate above changes. Drop misguided attempt to + (create_token): Accommodate above changes. Drop misguided attempt to add MIC SIDs to created user token. Print returned token as hex value. (subauth): Disable. (lsaauth): New function implementing client side of LSA authentication. - * security.h (class cygsid): Add well_known_sid attribute. Accomodate + * security.h (class cygsid): Add well_known_sid attribute. Accommodate throughout. Add *= operator to create a well known SID. (class cygsidlist): Rename count to cnt. Make count a method. (cygsidlist::add): Move to sec_helper.cc. @@ -351,7 +389,7 @@ (fhandler_dev_zero::mmap): Ditto. * shared.cc (shared_info::heap_slop_size): New method. (shared_info::heap_chunk_size): Don't use debug_printf at early stage. - * shared_info.h (SHARED_INFO_CB): Accomodate change to shared_info. + * shared_info.h (SHARED_INFO_CB): Accommodate change to shared_info. (CURR_SHARED_MAGIC): Ditto. (class shared_info): Add heap_slop member. Declare heap_slop_size. * wincap.h: Define heapslop throughout. @@ -388,7 +426,7 @@ 2006-10-23 Corinna Vinschen - * fhandler_disk_file.cc (fhandler_disk_file::rewinddir): Accomodate + * fhandler_disk_file.cc (fhandler_disk_file::rewinddir): Accommodate buggy RestartScan behaviour of Windows 2000. * wincap.h: Define has_buggy_restart_scan throughout. * wincap.cc: Ditto. @@ -423,7 +461,7 @@ get_reg_security. * security.h (cygpsid::operator PSID): Make method const, not the result. - (class security_descriptor): Add type member. Accomodate throughout. + (class security_descriptor): Add type member. Accommodate throughout. (security_descriptor::copy): New method. (security_descriptor::operator PSECURITY_DESCRIPTOR *): New operator. @@ -513,7 +551,7 @@ opening with backup intent. (fhandler_disk_file::readdir): Ditto when trying to retrieve file id explicitely. - * security.cc (check_file_access): Replace pbuf with correctly + * security.cc (check_file_access): Replace pbuf with correctly PPRIVILEGE_SET typed pset. Check explicitely for backup and/or restore privileges when AccessCheck fails, to circumvent AccessCheck shortcoming. Add comment to explain. @@ -653,13 +691,13 @@ * cygwin.din: Export posix_fadvise and posix_fallocate. * fhandler.cc (fhandler_base::fadvise): New method. (fhandler_base::ftruncate): Add allow_truncate parameter. - * fhandler.h (class fhandler_base): Add fadvise method. Accomodate + * fhandler.h (class fhandler_base): Add fadvise method. Accommodate new parameter to ftruncate. (class fhandler_pipe): Add fadvise and ftruncate methods. - (class fhandler_disk_file): Add fadvise method. Accomodate new + (class fhandler_disk_file): Add fadvise method. Accommodate new parameter to ftruncate. * fhandler_disk_file.cc (fhandler_disk_file::fadvise): New method. - (fhandler_disk_file::ftruncate): Accomodate new allow_truncate + (fhandler_disk_file::ftruncate): Accommodate new allow_truncate parameter. Set EOF using NtSetInformationFile on NT. * ntdll.h (struct _FILE_END_OF_FILE_INFORMATION): Define. (NtSetInformationFile): Declare. @@ -667,7 +705,7 @@ (fhandler_pipe::ftruncate): Ditto. * syscalls.cc (posix_fadvise): New function. (posix_fallocate): Ditto. - (ftruncate64): Accomodate second parameter to fhandler's ftruncate + (ftruncate64): Accommodate second parameter to fhandler's ftruncate method. * include/fcntl.h: Add POSIX_FADV_* flags. Add declarations of posix_fadvise and posix_fallocate. @@ -842,9 +880,9 @@ * cygtls.h: Drop socket related includes. (struct _local_storage): Remove exitsock and exitsock_sin. Add select_sockevt. - * cygtls.cc: Accomodate above change throughout. + * cygtls.cc: Accommodate above change throughout. * fhandler.h (class fhandler_socket): Make wsock_evt public. - * fhandler_socket.cc (fhandler_socket::fhandler_socket): Accomodate + * fhandler_socket.cc (fhandler_socket::fhandler_socket): Accommodate reordering members. (fhandler_socket::evaluate_events): Drop FD_CONNECT event as soon as it gets read once. Never remove FD_WRITE event here. @@ -857,7 +895,7 @@ (fhandler_socket::send_internal): Drop FD_WRITE event from wsock_events if the call to WSASendTo fails with WSAEWOULDBLOCK. Fix return value condition. - * select.cc (struct socketinf): Change to accomodate using socket event + * select.cc (struct socketinf): Change to accommodate using socket event handling. (peek_socket): Use event handling for peeking socket. (thread_socket): Ditto. @@ -885,14 +923,14 @@ (fhandler_socket::wait_for_events): Second half of former wait method. Call evaluate_events and wait in a loop if socket is blocking. (fhandler_socket::release_events): Rename from release. - (fhandler_socket::connect): Accomodate above name changes. + (fhandler_socket::connect): Accommodate above name changes. (fhandler_socket::accept): Ditto. (fhandler_socket::recv_internal): Ditto. (fhandler_socket::send_internal): Ditto. (fhandler_socket::close): Ditto. (fhandler_socket::fcntl): Always set owner to given input value on F_SETOWN. Handle F_GETOWN. - * net.cc (fdsock): Accomodate above name changes. + * net.cc (fdsock): Accommodate above name changes. 2006-07-20 Corinna Vinschen @@ -932,7 +970,7 @@ * mmap.cc (mmap_is_attached_or_noreserve_page): Rename mmap_is_attached_or_noreserve. Add region length parameter. Return enum above. - * exceptions.cc (_cygtls::handle_exceptions): Accomodate above. + * exceptions.cc (_cygtls::handle_exceptions): Accommodate above. * fhandler.cc (fhandler_base::raw_read): Call above for NOACCESS errors and retry on success to allow reads into untouched MAP_NORESERVE buffers. @@ -1102,7 +1140,7 @@ * fhandler.h (class fhandler_socket): Add wsock_mtx, wsock_evt and wsock_events members. Remove closed status flag, add listener - status flag. Accomodate new implementation of socket event handling + status flag. Accommodate new implementation of socket event handling methods. Declare recv* and send* functions ssize_t as the POSIX equivalents. (fhandler_socket::recv_internal): Declare. @@ -1130,9 +1168,9 @@ mutex handle and event handle. (fhandler_socket::dup): Duplicate wsock_mtx and wsock_evt. Fix copy-paste error in debug output. - (fhandler_socket::connect): Accomodate new event handling. + (fhandler_socket::connect): Accommodate new event handling. (fhandler_socket::listen): Set listener flag on successful listen. - (fhandler_socket::accept): Accomodate new event handling. + (fhandler_socket::accept): Accommodate new event handling. (fhandler_socket::recv_internal): New inline method centralizing common recv code. (fhandler_socket::recvfrom): Call recv_internal now. @@ -1202,14 +1240,14 @@ * cygwin.din: Export in6addr_any, in6addr_loopback, freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo. * fhandler_socket.cc: Include cygwin/in6.h. - (get_inet_addr): Accomodate AF_INET6 usage. + (get_inet_addr): Accommodate AF_INET6 usage. (fhandler_socket::connect): Ditto. (fhandler_socket::listen): Ditto. (fhandler_socket::sendto): Ditto. * net.cc: Include cygwin/in6.h. (in6addr_any): Define. (in6addr_loopback): Define. - (cygwin_socket): Accomodate AF_INET6 usage. + (cygwin_socket): Accommodate AF_INET6 usage. (socketpair): Bind socketpairs only to loopback for security. (inet_pton4): New static function. (inet_pton6): Ditto. @@ -1263,7 +1301,7 @@ RegGetKeySecurity return value. * security.h (get_logon_server): Remove default vaue from wserver parameter. Add rediscovery parameter. - * uinfo.cc (cygheap_user::env_logsrv): Accomodate rediscovery parameter + * uinfo.cc (cygheap_user::env_logsrv): Accommodate rediscovery parameter in call to get_logon_server. 2006-07-05 Christopher Faylor @@ -1333,13 +1371,13 @@ NtQueryEaFile. (write_ea): Rename from NTWriteEA and rewrite using NtSetEaFile. * path.cc (get_symlink_ea): Make static. Add handle parameter to - accomodate new read_ea call. - (set_symlink_ea): Make static. Add handle parameter to accomodate new + accommodate new read_ea call. + (set_symlink_ea): Make static. Add handle parameter to accommodate new write_ea call. (symlink_worker): Call set_symlink_ea while file is still open. (symlink_info::check): Call get_symlink_ea after file has been opened. - * security.cc (get_file_attribute): Accomodate new read_ea call. - (set_file_attribute): Accomodate new write_ea call. + * security.cc (get_file_attribute): Accommodate new read_ea call. + (set_file_attribute): Accommodate new write_ea call. * security.h (read_ea): Change declaration accordingly. (write_ea): Ditto. @@ -1884,9 +1922,9 @@ (path_conv::isgood_inode): Centralized function to recognize a good inode number. (fhandler_base::fstat_by_handle): Constify fvi_size and fai_size. - Accomodate argument change in fstat_helper. + Accommodate argument change in fstat_helper. (fhandler_base::fstat_by_name): Ditto. - (fhandler_base::fstat_helper): Accomodate argument change. Call + (fhandler_base::fstat_helper): Accommodate argument change. Call path_conv::isgood_inode to recognize good inodes. (fhandler_disk_file::opendir): Explain Samba weirdness here. Call path_conv::fs_is_samba instead of path_conv::is_samba. diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h index d2b712e88..41abe00f6 100644 --- a/winsup/cygwin/child_info.h +++ b/winsup/cygwin/child_info.h @@ -23,7 +23,6 @@ enum child_status _CI_STRACED = 0x01, _CI_ISCYGWIN = 0x02, _CI_SAW_CTRL_C = 0x04 - }; #define OPROC_MAGIC_MASK 0xff00ff00 @@ -38,7 +37,7 @@ enum child_status #define EXEC_MAGIC_SIZE sizeof(child_info) /* Change this value if you get a message indicating that it is out-of-sync. */ -#define CURR_CHILD_INFO_MAGIC 0x3a24db6aU +#define CURR_CHILD_INFO_MAGIC 0x3ebda16aU /* NOTE: Do not make gratuitous changes to the names or organization of the below class. The layout is checksummed to determine compatibility between @@ -46,7 +45,7 @@ enum child_status class child_info { public: - DWORD zero[4]; // must be zeroed + DWORD msv_count; // zeroed on < W2K3, set to pseudo-count on Vista DWORD cb; // size of this record DWORD intro; // improbable string unsigned long magic; // magic number unique to child_info @@ -85,6 +84,7 @@ public: jmp_buf jmp; // where child will jump to void *stacktop; // location of top of parent stack void *stackbottom; // location of bottom of parent stack + char filler[4]; child_info_fork (); void handle_fork () __attribute__ ((regparm (1)));; bool handle_failure (DWORD) __attribute__ ((regparm (2))); @@ -109,6 +109,9 @@ class child_info_spawn: public child_info { public: cygheap_exec_info *moreinfo; + int __stdin; + int __stdout; + char filler[4]; ~child_info_spawn () { diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 38b4b67f3..727163e08 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -425,9 +425,7 @@ check_sanity_and_sync (per_process *p) /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */ /* about changing it]. */ if (sizeof (per_process) != SIZEOF_PER_PROCESS) - { - api_fatal ("per_process sanity check failed"); - } + api_fatal ("per_process sanity check failed"); /* Make sure that the app and the dll are in sync. */ @@ -590,48 +588,17 @@ child_info * get_cygwin_startup_info () { STARTUPINFO si; - DWORD zeros[sizeof (child_proc_info->zero) - / sizeof (child_proc_info->zero[0])] = {0}; GetStartupInfo (&si); child_info *res = (child_info *) si.lpReserved2; - /* It appears that when running under WOW64 on Vista 64, the first DWORD - value in the datastructure lpReserved2 is pointing to (zero[0] in - Cygwin), has to reflect the size of that datastructure as used in the - Microsoft C runtime (a count value, counting the number of elements in - two subsequent arrays, BYTE[count and HANDLE[count]), even though the C - runtime isn't used. Otherwise, if zero[0] is 0 or too small, the - datastructure gets overwritten. - - This seems to be a bug in Vista's WOW64, which apparently copies the - lpReserved2 datastructure not using the cbReserved2 size information, - but using the information given in the first DWORD within lpReserved2 - instead. 32 bit Windows and former WOW64 don't care if zero[0] is 0 - or a sensible non-0 count value. However, it's not clear if a non-0 - count doesn't result in trying to evaluate the content, so we do this - really only for Vista 64 for now. - - exec/spawn as well as fork write an appropriate value into zero[0] now, - depending on the wincap.needs_count_in_si_lpres2 flag. The value is - sizeof (child_info_*) / 5 which results in a count which covers the - full datastructure, plus not more than 4 extra bytes. This is ok as - long as the child_info structure is cosily stored within a bigger - datastructure. */ - if (wincap.needs_count_in_si_lpres2 ()) - zeros[0] = si.cbReserved2 / 5; - if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res - || memcmp (res->zero, zeros, sizeof (res->zero)) != 0) + || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC) res = NULL; else { if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC) multiple_cygwin_problem ("proc intro", res->intro, 0); - else if (res->intro == PROC_MAGIC_GENERIC - && res->magic != CHILD_INFO_MAGIC) - multiple_cygwin_problem ("proc magic", res->magic, - CHILD_INFO_MAGIC); else if (res->cygheap != (void *) &_cygheap_start) multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap, (DWORD) &_cygheap_start); @@ -718,6 +685,11 @@ child_info_spawn::handle_spawn () envc = moreinfo->envc; if (!dynamically_loaded) cygheap->fdtab.fixup_after_exec (); + if (__stdin >= 0) + cygheap->fdtab.move_fd (__stdin, 0); + if (__stdout >= 0) + cygheap->fdtab.move_fd (__stdout, 1); + ready (true); /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index bb84574d4..b436c88c6 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -662,6 +662,14 @@ dtable::fixup_before_fork (DWORD target_proc_id) unlock (); } +void +dtable::move_fd (int from, int to) +{ + // close (to); /* It is assumed that this is close-on-exec */ + fds[to] = fds[from]; + fds[from] = NULL; +} + void dtable::fixup_before_exec (DWORD target_proc_id) { diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index 5e136ab9b..bc52a8f1a 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -45,6 +45,7 @@ public: bool need_fixup_before () { return cnt_need_fixup_before > 0; } + void move_fd (int, int); int vfork_child_dup (); void vfork_parent_restore (); void vfork_child_fixup (); diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index f6882e874..5070855dd 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1534,19 +1534,23 @@ fhandler_dev_null::open (int flags, mode_t mode) } void -fhandler_base::set_no_inheritance (HANDLE &h, int not_inheriting) +fhandler_base::set_no_inheritance (HANDLE &h, bool not_inheriting) { - HANDLE oh = h; - /* Note that we could use SetHandleInformation here but it is not available - on all platforms. Test cases seem to indicate that using DuplicateHandle - in this fashion does not actually close the original handle, which is - what we want. If this changes in the future, we may be forced to use - SetHandleInformation on newer OS's */ - if (!DuplicateHandle (hMainProc, oh, hMainProc, &h, 0, !not_inheriting, - DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) - debug_printf ("DuplicateHandle failed, %E"); - if (oh != h) - VerifyHandle (h); + if (wincap.has_set_handle_information ()) + { + if (!SetHandleInformation (h, HANDLE_FLAG_INHERIT, not_inheriting ? 0 : HANDLE_FLAG_INHERIT)) + debug_printf ("SetHandleInformation failed, %E"); + } + else + { + HANDLE oh = h; + if (!DuplicateHandle (hMainProc, oh, hMainProc, &h, 0, !not_inheriting, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + debug_printf ("DuplicateHandle failed, %E"); + + if (oh != h) + VerifyHandle (h); + } #ifdef DEBUGGING_AND_FDS_PROTECTED if (h) setclexec (oh, h, not_inheriting); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index af267d92c..6e7bf4821 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -167,7 +167,7 @@ class fhandler_base void set_flags (int x, int supplied_bin = 0); bool is_nonblocking (); - void set_nonblocking (int yes); + void set_nonblocking (int); bool wbinary () const { return status.wbinset ? status.wbinary : 1; } bool rbinary () const { return status.rbinset ? status.rbinary : 1; } @@ -249,15 +249,15 @@ class fhandler_base virtual char *get_proc_fd_name (char *buf); virtual void hclose (HANDLE h) {CloseHandle (h);} - virtual void set_no_inheritance (HANDLE &h, int not_inheriting); + virtual void set_no_inheritance (HANDLE &, bool); /* fixup fd possibly non-inherited handles after fork */ - bool fork_fixup (HANDLE parent, HANDLE &h, const char *name); + bool fork_fixup (HANDLE, HANDLE &, const char *); virtual bool need_fixup_before () const {return false;} - int open_9x (int flags, mode_t mode = 0); - virtual int open (int flags, mode_t mode = 0); - int open_fs (int flags, mode_t mode = 0); + int open_9x (int, mode_t = 0); + virtual int open (int, mode_t = 0); + int open_fs (int, mode_t = 0); virtual int close (); int close_fs (); virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); @@ -520,8 +520,12 @@ protected: HANDLE writepipe_exists; DWORD orig_pid; unsigned id; +private: + pid_t popen_pid; public: fhandler_pipe (); + void set_popen_pid (pid_t pid) {popen_pid = pid;} + pid_t get_popen_pid () const {return popen_pid;} _off64_t lseek (_off64_t offset, int whence); select_record *select_read (select_record *s); select_record *select_write (select_record *s); diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index cc5beceb7..b94a28d0b 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -284,10 +284,6 @@ frok::parent (void *stack_here) si.lpReserved2 = (LPBYTE) &ch; si.cbReserved2 = sizeof (ch); - /* See comment in dcrt0.cc, function get_cygwin_startup_info. */ - if (wincap.needs_count_in_si_lpres2 ()) - ch.zero[0] = sizeof (ch) / 5; - syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)", myself->progname, myself->progname, c_flags, &si, &pi); bool locked = __malloc_lock (); diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index d56b32aff..99231e7f1 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -32,7 +32,7 @@ static const NO_COPY char pipeid_fmt[] = "stupid_pipe.%u.%u"; fhandler_pipe::fhandler_pipe () : fhandler_base (), guard (NULL), broken_pipe (false), writepipe_exists (NULL), - orig_pid (0), id (0) + orig_pid (0), id (0), popen_pid (0) { need_fork_fixup (true); } @@ -280,6 +280,7 @@ fhandler_pipe::dup (fhandler_base *child) { int res = -1; fhandler_pipe *ftp = (fhandler_pipe *) child; + ftp->set_popen_pid (0); ftp->guard = ftp->writepipe_exists = ftp->read_state = NULL; if (get_handle () && fhandler_base::dup (child)) diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 4c4b7bc72..4e54a7558 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -253,9 +253,6 @@ shared_info::heap_slop_size () heap_slop = 0; else heap_slop <<= 20; -#ifdef DEBUGGING - system_printf ("fixed heap slop is %p", heap_slop); -#endif } return heap_slop; @@ -287,9 +284,6 @@ shared_info::heap_chunk_size () heap_chunk <<= 20; if (!heap_chunk) heap_chunk = 384 * 1024 * 1024; -#ifdef DEBUGGING - system_printf ("fixed heap size is %u", heap_chunk); -#endif } return heap_chunk; diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index a1a4be0db..d9b37d72a 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -145,7 +145,7 @@ public: #define SHARED_INFO_CB 19988 -#define CURR_SHARED_MAGIC 0xb632a4cU +#define CURR_SHARED_MAGIC 0x87c42d1eU /* NOTE: Do not make gratuitous changes to the names or organization of the below class. The layout is checksummed to determine compatibility between diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index d2c9109c8..3a764fe63 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -787,6 +787,9 @@ child_info::child_info (unsigned in_cb, child_info_types chtype, bool need_subpr { memset (this, 0, in_cb); cb = in_cb; + + msv_count = in_cb / 5; + intro = PROC_MAGIC_GENERIC; magic = CHILD_INFO_MAGIC; type = chtype; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 12418df92..352e51c87 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -210,7 +210,7 @@ find_exec (const char *name, path_conv& buf, const char *mywinenv, /* Utility for spawn_guts. */ static HANDLE -handle (int fd, int direction) +handle (int fd, bool writing) { HANDLE h; cygheap_fdget cfd (fd); @@ -219,10 +219,11 @@ handle (int fd, int direction) h = INVALID_HANDLE_VALUE; else if (cfd->close_on_exec ()) h = INVALID_HANDLE_VALUE; - else if (direction == 0) + else if (!writing) h = cfd->get_handle (); else h = cfd->get_output_handle (); + return h; } @@ -259,9 +260,9 @@ do_cleanup (void *args) } -static int __stdcall +int __stdcall spawn_guts (const char * prog_arg, const char *const *argv, - const char *const envp[], int mode) + const char *const envp[], int mode, int __stdin, int __stdout) { bool rc; pid_t cygpid; @@ -298,14 +299,7 @@ spawn_guts (const char * prog_arg, const char *const *argv, pthread_cleanup_push (do_cleanup, (void *) &cleanup); av newargv; linebuf one_line; - /* Allocate slightly bigger for call to CreateProcess to accomodate - needs_count_in_si_lpres2. */ - struct { - child_info_spawn ch; - char filler[4]; - } _ch; -#define ch _ch.ch - + child_info_spawn ch; char *envblock = NULL; path_conv real_path; bool reset_sendsig = false; @@ -316,7 +310,8 @@ spawn_guts (const char * prog_arg, const char *const *argv, cygheap_exec_info *moreinfo; bool null_app_name = false; - STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL}; + STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, + NULL, NULL, NULL}; int looped = 0; HANDLE orig_wr_proc_pipe = NULL; @@ -411,10 +406,13 @@ spawn_guts (const char * prog_arg, const char *const *argv, pi.dwProcessId = pi.dwThreadId = 0; si.lpReserved = NULL; si.lpDesktop = NULL; + + /* Set up needed handles for stdio */ si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = handle (0, 0); /* Get input handle */ - si.hStdOutput = handle (1, 1); /* Get output handle */ - si.hStdError = handle (2, 1); /* Get output handle */ + si.hStdInput = handle ((__stdin < 0 ? 0 : __stdin), false); + si.hStdOutput = handle ((__stdout < 0 ? 1 : __stdout), true); + si.hStdError = handle (2, true); + si.cb = sizeof (si); if (!wincap.pty_needs_alloc_console () && newargv.iscui && myself->ctty == -1) { @@ -483,14 +481,12 @@ spawn_guts (const char * prog_arg, const char *const *argv, } ch.set (chtype, real_path.iscygexec ()); ch.moreinfo = moreinfo; + ch.__stdin = __stdin; + ch.__stdout = __stdout; si.lpReserved2 = (LPBYTE) &ch; si.cbReserved2 = sizeof (ch); - /* See comment in dcrt0.cc, function get_cygwin_startup_info. */ - if (wincap.needs_count_in_si_lpres2 ()) - ch.zero[0] = sizeof (ch) / 5; - /* When ruid != euid we create the new process under the current original account and impersonate in child, this way maintaining the different effective vs. real ids. diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index bde4d65cf..4a3114d4c 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -40,6 +40,7 @@ details. */ #include #include #include +#include #include #include #include @@ -3242,3 +3243,109 @@ funlockfile (FILE *file) { _funlockfile (file); } + +extern "C" FILE * +popen (const char *command, const char *type) +{ + int fds[2]; + + if (pipe (fds) < 0) + return NULL; + int fd, other_fd, __stdin, __stdout, stdwhat; + if (type[1] != '\0') + { + set_errno (EINVAL); + return NULL; + } + if (*type == 'r') + { + __stdin = -1; + stdwhat = 1; + other_fd = __stdout = fds[1]; + fd = fds[0]; + } + else if (*type == 'w') + { + __stdout = -1; + stdwhat = 0; + other_fd = __stdin = fds[0]; + fd = fds[1]; + } + else + { + set_errno (EINVAL); + return NULL; + } + + FILE *fp = fdopen (fd, type); + fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC); + + if (!fp) + goto err; + + pid_t pid; + const char *argv[4]; + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = command; + argv[3] = NULL; + + { + lock_process now; + int state = fcntl (stdwhat, F_GETFD, 0); + fcntl (stdwhat, F_SETFD, state | FD_CLOEXEC); + pid = spawn_guts ("/bin/sh", argv, cur_environ (), _P_NOWAIT, + __stdin, __stdout); + fcntl (stdwhat, F_SETFD, state); + } + + if (pid < 0) + goto err; + close (other_fd); + + fhandler_pipe *fh = (fhandler_pipe *) cygheap->fdtab[fd]; + fh->set_popen_pid (pid); + + return fp; + +err: + int save_errno = get_errno (); + close (fds[0]); + close (fds[1]); + set_errno (save_errno); + return NULL; +} + +int +pclose (FILE *fp) +{ + fhandler_pipe *fh = (fhandler_pipe *) cygheap->fdtab[fileno(fp)]; + + if (fh->get_device () != FH_PIPEW && fh->get_device () != FH_PIPER) + { + set_errno (EBADF); + return -1; + } + + int pid = fh->get_popen_pid (); + if (!pid) + { + set_errno (ECHILD); + return -1; + } + + if (fclose (fp)) + return -1; + + int status; + while (1) + if (waitpid (pid, &status, 0) == pid) + break; + else if (get_errno () == EINTR) + continue; + else + return -1; + + return status; +} diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 4c0f514f3..9e9aea271 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -170,6 +170,9 @@ void dll_crt0 (per_process *) __asm__ ("_dll_crt0__FP11per_process"); extern "C" void __stdcall _dll_crt0 (); extern void dll_crt0_1 (void *); extern void dll_dllcrt0_1 (void *); +extern int __stdcall spawn_guts (const char * prog_arg, const char *const *argv, + const char *const envp[], int mode, + int __stdin = -1, int __stdout = -1); /* dynamically loaded dll initialization */ extern "C" int dll_dllcrt0 (HMODULE, per_process *);