From f7cb52eec7144ec100874781bc36c301b027e01d Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 27 Oct 2014 11:33:53 +0000 Subject: [PATCH] * cygheap.cc (cygheap_fixup_in_child): Drop call to set_dll_dir. (init_cygheap::init_installation_root): Set installation_dir_len. (setup_cygheap): Drop call to set_dll_dir. * cygheap.h (struct init_cygheap): Add installation_dir_len member. (init_cygheap::set_dll_dir): Remove. * environ.cc (win_env::add_cache): Use stpcpy for speed. (posify_maybe): Use tmp_pathbuf buffer instead of stack. (raise_envblock): New function to resize Windows environment block. (build_env): Fix indentation. Call raise_envblock function. Check if $PATH exists and is non-empty. If not, add PATH variable with Cygwin installation directory as content to Windows environment. Explain why. * uinfo.cc (cygheap_pwdgrp::_nss_init): Fill UNICODE_STRING members on the fly. Drop call to RtlInitUnicodeString. (pwdgrp::check_file): Ditto. --- winsup/cygwin/ChangeLog | 18 ++++++++ winsup/cygwin/cygheap.cc | 9 ++-- winsup/cygwin/cygheap.h | 10 +---- winsup/cygwin/environ.cc | 82 +++++++++++++++++++++++------------- winsup/cygwin/release/1.7.33 | 5 ++- winsup/cygwin/uinfo.cc | 16 +++---- 6 files changed, 87 insertions(+), 53 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 79f32e7ca..69d37e89b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2014-10-27 Corinna Vinschen + + * cygheap.cc (cygheap_fixup_in_child): Drop call to set_dll_dir. + (init_cygheap::init_installation_root): Set installation_dir_len. + (setup_cygheap): Drop call to set_dll_dir. + * cygheap.h (struct init_cygheap): Add installation_dir_len member. + (init_cygheap::set_dll_dir): Remove. + * environ.cc (win_env::add_cache): Use stpcpy for speed. + (posify_maybe): Use tmp_pathbuf buffer instead of stack. + (raise_envblock): New function to resize Windows environment block. + (build_env): Fix indentation. Call raise_envblock function. Check if + $PATH exists and is non-empty. If not, add PATH variable with Cygwin + installation directory as content to Windows environment. Explain why. + + * uinfo.cc (cygheap_pwdgrp::_nss_init): Fill UNICODE_STRING members + on the fly. Drop call to RtlInitUnicodeString. + (pwdgrp::check_file): Ditto. + 2014-10-26 Corinna Vinschen * fhandler_socket.cc (fhandler_socket::af_local_connect): Drop diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 8e25a07ea..97090affc 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -83,7 +83,6 @@ cygheap_fixup_in_child (bool execed) _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap); child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL); cygheap_init (); - cygheap->set_dll_dir (); debug_fixup_after_fork_exec (); if (execed) { @@ -188,9 +187,10 @@ init_cygheap::init_installation_root () "Invalid DLL path"); /* Copy result into installation_dir before stripping off "bin" dir and - revert to Win32 path. This path is used in cygheap_init to call - SetDllDirectory. */ - wcpncpy (installation_dir, installation_root, PATH_MAX); + revert to Win32 path. This path is added to the Windows environment + in buildenv. See there for a description. */ + installation_dir_len = wcpncpy (installation_dir, installation_root, PATH_MAX) + - installation_dir; installation_dir[1] = L'\\'; /* If w < p, the Cygwin DLL resides in the root dir of a drive or network @@ -264,7 +264,6 @@ setup_cygheap () cygheap_init (); cygheap->user.init (); cygheap->init_installation_root (); /* Requires user.init! */ - cygheap->set_dll_dir (); cygheap->pg.init (); } diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 55f26ed36..ff86d5ef3 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -506,6 +506,7 @@ struct init_cygheap: public mini_cygheap char *buckets[NBUCKETS]; WCHAR installation_root[PATH_MAX]; WCHAR installation_dir[PATH_MAX]; + size_t installation_dir_len; UNICODE_STRING installation_key; WCHAR installation_key_buf[18]; cygheap_root root; @@ -534,15 +535,6 @@ struct init_cygheap: public mini_cygheap hook_chain hooks; void close_ctty (); void init_installation_root (); - void set_dll_dir () - { - /* Call SetDllDirectory on installation_dir. This removes "." from the - DLL search path and installs our /bin dir instead. - Amazing but true: This setting is propagated to child processes :-) - but only starting with Windows 8 :-( */ - if (!SetDllDirectoryW (installation_dir)) - debug_printf ("SetDllDirectoryW (%W), %E", installation_dir); - } void __reg1 init_tls_list ();; void __reg2 add_tls (_cygtls *); void __reg3 remove_tls (_cygtls *, DWORD); diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 817439b0a..9b9be4a00 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -396,18 +396,15 @@ win_env::add_cache (const char *in_posix, const char *in_native) if (in_native) { native = (char *) realloc (native, namelen + 1 + strlen (in_native)); - strcpy (native, name); - strcpy (native + namelen, in_native); + stpcpy (stpcpy (native, name), in_native); } else { tmp_pathbuf tp; char *buf = tp.c_get (); - strcpy (buf, name + namelen); towin32 (in_posix, buf, NT_MAX_PATH); native = (char *) realloc (native, namelen + 1 + strlen (buf)); - strcpy (native, name); - strcpy (native + namelen, buf); + stpcpy (stpcpy (native, name), buf); } MALLOC_CHECK; if (immediate && cygwin_finished_initializing) @@ -480,8 +477,9 @@ posify_maybe (char **here, const char *value, char *outenv) { /* The conversion routine removed elements from a path list so we have to recalculate the windows path to remove elements there, too. */ - char cleanvalue[strlen (value) + 1]; - conv->towin32 (newvalue, cleanvalue, sizeof cleanvalue); + tmp_pathbuf tp; + char *cleanvalue = tp.c_get (); + conv->towin32 (newvalue, cleanvalue, NT_MAX_PATH); conv->add_cache (newvalue, cleanvalue); } @@ -1032,6 +1030,21 @@ spenv::retrieve (bool no_envblock, const char *const env) return getwinenveq (name, namelen, HEAP_1_STR); } +static inline int +raise_envblock (int new_tl, PWCHAR &envblock, PWCHAR &s) +{ + int tl = new_tl + 100; + PWCHAR new_envblock = + (PWCHAR) realloc (envblock, (2 + tl) * sizeof (WCHAR)); + /* If realloc moves the block, move `s' with it. */ + if (new_envblock != envblock) + { + s += new_envblock - envblock; + envblock = new_envblock; + } + return tl; +} + #define SPENVS_SIZE (sizeof (spenvs) / sizeof (spenvs[0])) /* Create a Windows-style environment block, i.e. a typical character buffer @@ -1096,14 +1109,14 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, for (unsigned i = 0; i < SPENVS_SIZE; i++) if (!saw_spenv[i] && (spenvs[i].force_into_environment || cygheap->user.issetuid ())) { - *dstp = spenvs[i].retrieve (false); - if (*dstp && *dstp != env_dontadd) - { - *pass_dstp++ = *dstp; - tl += strlen (*dstp) + 1; - dstp++; - } - } + *dstp = spenvs[i].retrieve (false); + if (*dstp && *dstp != env_dontadd) + { + *pass_dstp++ = *dstp; + tl += strlen (*dstp) + 1; + dstp++; + } + } envc = dstp - newenv; /* Number of entries in newenv */ assert ((size_t) envc <= (n + SPENVS_SIZE)); @@ -1126,6 +1139,7 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, PWCHAR s; envblock = (PWCHAR) malloc ((2 + tl) * sizeof (WCHAR)); int new_tl = 0; + bool saw_PATH = false; for (srcp = pass_env, s = envblock; *srcp; srcp++) { const char *p; @@ -1144,7 +1158,17 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, /* See if this entry requires posix->win32 conversion. */ conv = getwinenv (*srcp, rest, &temp); if (conv) - p = conv->native; /* Use win32 path */ + { + p = conv->native; /* Use win32 path */ + /* Does PATH exist in the environment? */ + if (**srcp == 'P') + { + /* And is it non-empty? */ + if (!conv->native || !conv->native[0]) + continue; + saw_PATH = true; + } + } else p = *srcp; /* Don't worry about it */ @@ -1153,19 +1177,9 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, /* See if we need to increase the size of the block. */ if (new_tl > tl) - { - tl = new_tl + 100; - PWCHAR new_envblock = - (PWCHAR) realloc (envblock, (2 + tl) * sizeof (WCHAR)); - /* If realloc moves the block, move `s' with it. */ - if (new_envblock != envblock) - { - s += new_envblock - envblock; - envblock = new_envblock; - } - } + tl = raise_envblock (new_tl, envblock, s); - int slen = sys_mbstowcs (s, len, p); + len = sys_mbstowcs (s, len, p); /* See if environment variable is "special" in a Windows sense. Under NT, the current directories for visited drives are stored @@ -1174,7 +1188,17 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc, if (s[0] == L'!' && (iswdrive (s + 1) || (s[1] == L':' && s[2] == L':')) && s[3] == L'=') *s = L'='; - s += slen + 1; + s += len + 1; + } + /* If PATH doesn't exist in the environment, add a PATH with just + Cygwin's bin dir to the Windows env to allow loading system DLLs + during execve. */ + if (!saw_PATH) + { + new_tl += cygheap->installation_dir_len + 5; + if (new_tl > tl) + tl = raise_envblock (new_tl, envblock, s); + s = wcpcpy (wcpcpy (s, L"PATH="), cygheap->installation_dir) + 1; } *s = L'\0'; /* Two null bytes at the end */ assert ((s - envblock) <= tl); /* Detect if we somehow ran over end diff --git a/winsup/cygwin/release/1.7.33 b/winsup/cygwin/release/1.7.33 index c64d2d3a1..c7acd071d 100644 --- a/winsup/cygwin/release/1.7.33 +++ b/winsup/cygwin/release/1.7.33 @@ -42,8 +42,9 @@ What changed: are supposed to work. Finally implement a CLASS_OBJ emulation. Update getfacl(1)/setfacl(1) accordingly. -- Drop the current working directory from the default DLL search path in - favor of Cygwin's /bin dir. +- When exec'ing applications, check if $PATH exists and is non-empty. If not, + add PATH variable with Cygwin installation directory as content to Windows + environment to allow loading of Cygwin system DLLs. - Improve various header files for C++- and standards-compliance. diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 12d5069d1..75b447287 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -752,10 +752,11 @@ cygheap_pwdgrp::_nss_init () char *buf = tp.c_get (); PCWSTR rel_path = L"\\etc\\nsswitch.conf"; - path.Buffer = (PWCHAR) alloca ((wcslen (cygheap->installation_root) - + wcslen (rel_path) + 1) * sizeof (WCHAR)); + path.Length = (wcslen (cygheap->installation_root) + wcslen (rel_path)) + * sizeof (WCHAR); + path.MaximumLength = path.Length + sizeof (WCHAR); + path.Buffer = (PWCHAR) alloca (path.MaximumLength); wcpcpy (wcpcpy (path.Buffer, cygheap->installation_root), rel_path); - RtlInitUnicodeString (&path, path.Buffer); InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE, NULL, NULL); if (rl.init (&attr, buf, NT_MAX_PATH)) @@ -1045,12 +1046,11 @@ pwdgrp::check_file () if (!path.Buffer) { PCWSTR rel_path = is_group () ? L"\\etc\\group" : L"\\etc\\passwd"; - path.Buffer = (PWCHAR) cmalloc_abort (HEAP_BUF, - (wcslen (cygheap->installation_root) - + wcslen (rel_path) + 1) - * sizeof (WCHAR)); + path.Length = (wcslen (cygheap->installation_root) + wcslen (rel_path)) + * sizeof (WCHAR); + path.MaximumLength = path.Length + sizeof (WCHAR); + path.Buffer = (PWCHAR) cmalloc_abort (HEAP_BUF, path.MaximumLength); wcpcpy (wcpcpy (path.Buffer, cygheap->installation_root), rel_path); - RtlInitUnicodeString (&path, path.Buffer); InitializeObjectAttributes (&attr, &path, OBJ_CASE_INSENSITIVE, NULL, NULL); } -- 2.43.5