mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-01 03:50:28 +08:00
* autoload.cc (CreateEnvironmentBlock): Import.
(DestroyEnvironmentBlock): Import. * environ.cc (env_compare): New static bsearch comparison function. (build_env): Add parameter taking a user token. If token is non-NULL, fetch user's default Windows environment and merge it into the resulting environment. Explain what we do in preceeding comment. * environ,h (build_env): Align prototype to above change. * external.cc (create_winenv): Call build_env with NULL token. * spawn.cc (child_info_spawn::worker): When spawning new process under another user account, call build_env with new token to allow merging user's default Windows environment. * winlean.h (_USERENV_): Define to override dllimport.
This commit is contained in:
parent
0c326d84b5
commit
9119d13db8
@ -1,3 +1,18 @@
|
|||||||
|
2014-12-02 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* autoload.cc (CreateEnvironmentBlock): Import.
|
||||||
|
(DestroyEnvironmentBlock): Import.
|
||||||
|
* environ.cc (env_compare): New static bsearch comparison function.
|
||||||
|
(build_env): Add parameter taking a user token. If token is non-NULL,
|
||||||
|
fetch user's default Windows environment and merge it into the resulting
|
||||||
|
environment. Explain what we do in preceeding comment.
|
||||||
|
* environ,h (build_env): Align prototype to above change.
|
||||||
|
* external.cc (create_winenv): Call build_env with NULL token.
|
||||||
|
* spawn.cc (child_info_spawn::worker): When spawning new process under
|
||||||
|
another user account, call build_env with new token to allow merging
|
||||||
|
user's default Windows environment.
|
||||||
|
* winlean.h (_USERENV_): Define to override dllimport.
|
||||||
|
|
||||||
2014-12-02 Corinna Vinschen <corinna@vinschen.de>
|
2014-12-02 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* spawn.cc (child_info_spawn::worker): Fix formatting.
|
* spawn.cc (child_info_spawn::worker): Fix formatting.
|
||||||
|
@ -675,6 +675,9 @@ LoadDLLfunc (SetParent, 8, user32)
|
|||||||
LoadDLLfunc (SetProcessWindowStation, 4, user32)
|
LoadDLLfunc (SetProcessWindowStation, 4, user32)
|
||||||
LoadDLLfunc (SetThreadDesktop, 4, user32)
|
LoadDLLfunc (SetThreadDesktop, 4, user32)
|
||||||
|
|
||||||
|
LoadDLLfunc (CreateEnvironmentBlock, 12, userenv)
|
||||||
|
LoadDLLfunc (DestroyEnvironmentBlock, 4, userenv)
|
||||||
|
|
||||||
LoadDLLfuncEx3 (waveInAddBuffer, 12, winmm, 1, 0, 1)
|
LoadDLLfuncEx3 (waveInAddBuffer, 12, winmm, 1, 0, 1)
|
||||||
LoadDLLfuncEx3 (waveInClose, 4, winmm, 1, 0, 1)
|
LoadDLLfuncEx3 (waveInClose, 4, winmm, 1, 0, 1)
|
||||||
LoadDLLfuncEx3 (waveInGetNumDevs, 0, winmm, 1, 0, 1)
|
LoadDLLfuncEx3 (waveInGetNumDevs, 0, winmm, 1, 0, 1)
|
||||||
|
@ -9,12 +9,14 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "winsup.h"
|
#include "winsup.h"
|
||||||
|
#include <userenv.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <cygwin/version.h>
|
#include <cygwin/version.h>
|
||||||
#include "pinfo.h"
|
#include "pinfo.h"
|
||||||
#include "perprocess.h"
|
#include "perprocess.h"
|
||||||
@ -1047,14 +1049,39 @@ raise_envblock (int new_tl, PWCHAR &envblock, PWCHAR &s)
|
|||||||
|
|
||||||
#define SPENVS_SIZE (sizeof (spenvs) / sizeof (spenvs[0]))
|
#define SPENVS_SIZE (sizeof (spenvs) / sizeof (spenvs[0]))
|
||||||
|
|
||||||
|
int
|
||||||
|
env_compare (const void *key, const void *memb)
|
||||||
|
{
|
||||||
|
const char *k = *(const char **) key;
|
||||||
|
const char *m = *(const char **) memb;
|
||||||
|
|
||||||
|
char *ke = strchr (k, '=');
|
||||||
|
char *me = strchr (m, '=');
|
||||||
|
if (ke == NULL || me == NULL)
|
||||||
|
return strcasecmp (k, m);
|
||||||
|
int ret = strncasecmp (k, m, MIN (ke - k, me - m));
|
||||||
|
if (!ret)
|
||||||
|
ret = (ke - k) - (me - m);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a Windows-style environment block, i.e. a typical character buffer
|
/* Create a Windows-style environment block, i.e. a typical character buffer
|
||||||
filled with null terminated strings, terminated by double null characters.
|
filled with null terminated strings, terminated by double null characters.
|
||||||
Converts environment variables noted in conv_envvars into win32 form
|
Converts environment variables noted in conv_envvars into win32 form
|
||||||
prior to placing them in the string. */
|
prior to placing them in the string.
|
||||||
|
|
||||||
|
If new_token is set, we're going to switch the user account in
|
||||||
|
child_info_spawn::worker. If so, we're also fetching the Windows default
|
||||||
|
environment for the new user, and merge it into the environment we propage
|
||||||
|
to the child. */
|
||||||
char ** __reg3
|
char ** __reg3
|
||||||
build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
||||||
bool no_envblock)
|
bool no_envblock, HANDLE new_token)
|
||||||
{
|
{
|
||||||
|
PWCHAR cwinenv = NULL;
|
||||||
|
size_t winnum = 0;
|
||||||
|
char **winenv = NULL;
|
||||||
|
|
||||||
int len, n;
|
int len, n;
|
||||||
const char * const *srcp;
|
const char * const *srcp;
|
||||||
char **dstp;
|
char **dstp;
|
||||||
@ -1066,13 +1093,57 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
|||||||
for (n = 0; envp[n]; n++)
|
for (n = 0; envp[n]; n++)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Fetch windows env and convert to POSIX-style env. */
|
||||||
|
if (new_token
|
||||||
|
&& CreateEnvironmentBlock ((LPVOID *) &cwinenv, new_token, FALSE))
|
||||||
|
{
|
||||||
|
PWCHAR var = cwinenv;
|
||||||
|
while (*var)
|
||||||
|
{
|
||||||
|
++winnum;
|
||||||
|
var = wcschr (var, L'\0') + 1;
|
||||||
|
}
|
||||||
|
winenv = (char **) calloc (winnum + 1, sizeof (char *));
|
||||||
|
if (winenv)
|
||||||
|
{
|
||||||
|
for (winnum = 0, var = cwinenv;
|
||||||
|
*var;
|
||||||
|
++winnum, var = wcschr (var, L'\0') + 1)
|
||||||
|
sys_wcstombs_alloc (&winenv[winnum], HEAP_NOTHEAP, var);
|
||||||
|
}
|
||||||
|
DestroyEnvironmentBlock (cwinenv);
|
||||||
|
/* Eliminate variables which are already available in envp. The windows
|
||||||
|
env is sorted, so we can use bsearch. We're doing this first step,
|
||||||
|
so the following code doesn't allocate too much memory. */
|
||||||
|
if (winenv)
|
||||||
|
{
|
||||||
|
for (srcp = envp; *srcp; srcp++)
|
||||||
|
{
|
||||||
|
char **elem = (char **) bsearch (srcp, winenv, winnum,
|
||||||
|
sizeof *winenv, env_compare);
|
||||||
|
if (elem)
|
||||||
|
{
|
||||||
|
system_printf ("remove: %s", *elem);
|
||||||
|
free (*elem);
|
||||||
|
/* Use memmove to keep array sorted.
|
||||||
|
winnum - (elem - winenv) copies all elements following
|
||||||
|
elem, including the trailing NULL pointer. */
|
||||||
|
memmove (elem, elem + 1,
|
||||||
|
(winnum - (elem - winenv)) * sizeof *elem);
|
||||||
|
--winnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a new "argv-style" environ list with room for extra stuff. */
|
/* Allocate a new "argv-style" environ list with room for extra stuff. */
|
||||||
char **newenv = (char **) cmalloc_abort (HEAP_1_ARGV, sizeof (char *) *
|
char **newenv = (char **) cmalloc_abort (HEAP_1_ARGV, sizeof (char *) *
|
||||||
(n + SPENVS_SIZE + 1));
|
(n + winnum + SPENVS_SIZE + 1));
|
||||||
|
|
||||||
int tl = 0;
|
int tl = 0;
|
||||||
char **pass_dstp;
|
char **pass_dstp;
|
||||||
char **pass_env = (char **) alloca (sizeof (char *) * (n + SPENVS_SIZE + 1));
|
char **pass_env = (char **) alloca (sizeof (char *)
|
||||||
|
* (n + winnum + SPENVS_SIZE + 1));
|
||||||
/* Iterate over input list, generating a new environment list and refreshing
|
/* Iterate over input list, generating a new environment list and refreshing
|
||||||
"special" entries, if necessary. */
|
"special" entries, if necessary. */
|
||||||
for (srcp = envp, dstp = newenv, pass_dstp = pass_env; *srcp; srcp++)
|
for (srcp = envp, dstp = newenv, pass_dstp = pass_env; *srcp; srcp++)
|
||||||
@ -1107,19 +1178,49 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
|||||||
assert ((srcp - envp) == n);
|
assert ((srcp - envp) == n);
|
||||||
/* Fill in any required-but-missing environment variables. */
|
/* Fill in any required-but-missing environment variables. */
|
||||||
for (unsigned i = 0; i < SPENVS_SIZE; i++)
|
for (unsigned i = 0; i < SPENVS_SIZE; i++)
|
||||||
if (!saw_spenv[i] && (spenvs[i].force_into_environment || cygheap->user.issetuid ()))
|
if (!saw_spenv[i] && (spenvs[i].force_into_environment
|
||||||
|
|| cygheap->user.issetuid ()))
|
||||||
{
|
{
|
||||||
*dstp = spenvs[i].retrieve (false);
|
*dstp = spenvs[i].retrieve (false);
|
||||||
if (*dstp && *dstp != env_dontadd)
|
if (*dstp && *dstp != env_dontadd)
|
||||||
{
|
{
|
||||||
*pass_dstp++ = *dstp;
|
*pass_dstp++ = *dstp;
|
||||||
tl += strlen (*dstp) + 1;
|
tl += strlen (*dstp) + 1;
|
||||||
|
/* Eliminate from winenv. */
|
||||||
|
if (winenv)
|
||||||
|
{
|
||||||
|
char **elem = (char **) bsearch (dstp, winenv, winnum,
|
||||||
|
sizeof *winenv, env_compare);
|
||||||
|
if (elem)
|
||||||
|
{
|
||||||
|
system_printf ("remove: %s", *elem);
|
||||||
|
free (*elem);
|
||||||
|
memmove (elem, elem + 1,
|
||||||
|
(winnum - (elem - winenv)) * sizeof *elem);
|
||||||
|
--winnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
dstp++;
|
dstp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fill in any Windows environment vars still missing. */
|
||||||
|
if (winenv)
|
||||||
|
{
|
||||||
|
char **elem;
|
||||||
|
for (elem = winenv; *elem; ++elem)
|
||||||
|
{
|
||||||
|
*dstp = cstrdup1 (*elem);
|
||||||
|
free (*elem);
|
||||||
|
*pass_dstp++ = *dstp;
|
||||||
|
tl += strlen (*dstp) + 1;
|
||||||
|
++dstp;
|
||||||
|
}
|
||||||
|
free (winenv);
|
||||||
|
}
|
||||||
|
|
||||||
envc = dstp - newenv; /* Number of entries in newenv */
|
envc = dstp - newenv; /* Number of entries in newenv */
|
||||||
assert ((size_t) envc <= (n + SPENVS_SIZE));
|
assert ((size_t) envc <= (n + winnum + SPENVS_SIZE));
|
||||||
*dstp = NULL; /* Terminate */
|
*dstp = NULL; /* Terminate */
|
||||||
|
|
||||||
size_t pass_envc = pass_dstp - pass_env;
|
size_t pass_envc = pass_dstp - pass_env;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* environ.h: Declarations for environ manipulation
|
/* environ.h: Declarations for environ manipulation
|
||||||
|
|
||||||
Copyright 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2013 Red Hat, Inc.
|
Copyright 2000, 2001, 2002, 2003, 2005, 2006, 2008, 2013, 2014 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
@ -45,6 +45,6 @@ extern "C" char **__cygwin_environ, ***main_environ;
|
|||||||
extern "C" char __stdcall **cur_environ ();
|
extern "C" char __stdcall **cur_environ ();
|
||||||
#endif
|
#endif
|
||||||
char ** __reg3 build_env (const char * const *envp, PWCHAR &envblock,
|
char ** __reg3 build_env (const char * const *envp, PWCHAR &envblock,
|
||||||
int &envc, bool need_envblock);
|
int &envc, bool need_envblock, HANDLE new_token);
|
||||||
|
|
||||||
#define ENV_CVT -1
|
#define ENV_CVT -1
|
||||||
|
@ -138,7 +138,8 @@ create_winenv (const char * const *env)
|
|||||||
{
|
{
|
||||||
int unused_envc;
|
int unused_envc;
|
||||||
PWCHAR envblock = NULL;
|
PWCHAR envblock = NULL;
|
||||||
char **envp = build_env (env ?: cur_environ (), envblock, unused_envc, false);
|
char **envp = build_env (env ?: cur_environ (), envblock, unused_envc, false,
|
||||||
|
NULL);
|
||||||
PWCHAR p = envblock;
|
PWCHAR p = envblock;
|
||||||
|
|
||||||
if (envp)
|
if (envp)
|
||||||
|
@ -531,8 +531,14 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|||||||
if (!real_path.iscygexec())
|
if (!real_path.iscygexec())
|
||||||
::cygheap->fdtab.set_file_pointers_for_exec ();
|
::cygheap->fdtab.set_file_pointers_for_exec ();
|
||||||
|
|
||||||
|
/* If we switch the user, merge the user's Windows environment. */
|
||||||
|
bool switch_user = ::cygheap->user.issetuid ()
|
||||||
|
&& (::cygheap->user.saved_uid
|
||||||
|
!= ::cygheap->user.real_uid);
|
||||||
moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
|
moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
|
||||||
real_path.iscygexec ());
|
real_path.iscygexec (),
|
||||||
|
switch_user ? ::cygheap->user.primary_token ()
|
||||||
|
: NULL);
|
||||||
if (!moreinfo->envp || !envblock)
|
if (!moreinfo->envp || !envblock)
|
||||||
{
|
{
|
||||||
set_errno (E2BIG);
|
set_errno (E2BIG);
|
||||||
|
@ -28,6 +28,7 @@ details. */
|
|||||||
#define _SHELL32_
|
#define _SHELL32_
|
||||||
#define _SPOOL32_
|
#define _SPOOL32_
|
||||||
#define _USER32_
|
#define _USER32_
|
||||||
|
#define _USERENV_
|
||||||
#define _WINMM_
|
#define _WINMM_
|
||||||
#define WINIMPM
|
#define WINIMPM
|
||||||
#define WINSOCK_API_LINKAGE
|
#define WINSOCK_API_LINKAGE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user