1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-18 14:17:03 +01:00

common,w32: Fix setting environment variables on Windows.

* common/sysutils.c (gnupg_setenv): Also update the environment block
maintained by the C runtime.
(gnupg_unsetenv): Likewise.
* tests/gpgscm/ffi.c (do_setenv): Fix error handling.

Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
Justus Winter 2016-10-20 16:45:18 +02:00
parent bf37916a23
commit 8c7c4faf3d
2 changed files with 64 additions and 39 deletions

View File

@ -754,38 +754,51 @@ gnupg_setenv (const char *name, const char *value, int overwrite)
(void)value; (void)value;
(void)overwrite; (void)overwrite;
return 0; return 0;
#elif defined(HAVE_W32_SYSTEM) #else
if (!overwrite) #if defined(HAVE_W32_SYSTEM)
{ /* Windows maintains (at least) two sets of environment variables.
char tmpbuf[10]; One set can be accessed by GetEnvironmentVariable and
if (GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf)) SetEnvironmentVariable. This set is inherited by the children.
return 0; /* Exists but overwrite was not requested. */ The other set is maintained in the C runtime, and is accessed
} using getenv and putenv. We try to keep them in sync by
if (!SetEnvironmentVariable (name, value)) modifying both sets. */
{ {
gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */ int exists;
return -1; char tmpbuf[10];
} exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf);
return 0;
#elif defined(HAVE_SETENV) if ((! exists || overwrite) && !SetEnvironmentVariable (name, value))
{
gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
return -1;
}
}
#endif
#if defined(HAVE_SETENV)
return setenv (name, value, overwrite); return setenv (name, value, overwrite);
#else #else
char *buf; if (! getenv (name) || overwrite)
(void)overwrite;
if (!name || !value)
{ {
gpg_err_set_errno (EINVAL); char *buf;
return -1;
} (void)overwrite;
buf = xtrymalloc (strlen (name) + 1 + strlen (value) + 1); if (!name || !value)
if (!buf) {
return -1; gpg_err_set_errno (EINVAL);
strcpy (stpcpy (stpcpy (buf, name), "="), value); return -1;
}
buf = xtrymalloc (strlen (name) + 1 + strlen (value) + 1);
if (!buf)
return -1;
strcpy (stpcpy (stpcpy (buf, name), "="), value);
#if __GNUC__ #if __GNUC__
# warning no setenv - using putenv but leaking memory. # warning no setenv - using putenv but leaking memory.
#endif #endif
return putenv (buf); return putenv (buf);
}
return 0;
#endif
#endif #endif
} }
@ -796,30 +809,40 @@ gnupg_unsetenv (const char *name)
#ifdef HAVE_W32CE_SYSTEM #ifdef HAVE_W32CE_SYSTEM
(void)name; (void)name;
return 0; return 0;
#elif defined(HAVE_W32_SYSTEM) #else
#if defined(HAVE_W32_SYSTEM)
/* Windows maintains (at least) two sets of environment variables.
One set can be accessed by GetEnvironmentVariable and
SetEnvironmentVariable. This set is inherited by the children.
The other set is maintained in the C runtime, and is accessed
using getenv and putenv. We try to keep them in sync by
modifying both sets. */
if (!SetEnvironmentVariable (name, NULL)) if (!SetEnvironmentVariable (name, NULL))
{ {
gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */ gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
return -1; return -1;
} }
return 0; #endif
#elif defined(HAVE_UNSETENV) #if defined(HAVE_UNSETENV)
return unsetenv (name); return unsetenv (name);
#else #else
char *buf; {
char *buf;
if (!name) if (!name)
{ {
gpg_err_set_errno (EINVAL); gpg_err_set_errno (EINVAL);
return -1;
}
buf = xtrystrdup (name);
if (!buf)
return -1; return -1;
}
buf = xtrystrdup (name);
if (!buf)
return -1;
#if __GNUC__ #if __GNUC__
# warning no unsetenv - trying putenv but leaking memory. # warning no unsetenv - trying putenv but leaking memory.
#endif #endif
return putenv (buf); return putenv (buf);
}
#endif
#endif #endif
} }

View File

@ -236,7 +236,9 @@ do_setenv (scheme *sc, pointer args)
FFI_ARG_OR_RETURN (sc, char *, value, string, args); FFI_ARG_OR_RETURN (sc, char *, value, string, args);
FFI_ARG_OR_RETURN (sc, int, overwrite, bool, args); FFI_ARG_OR_RETURN (sc, int, overwrite, bool, args);
FFI_ARGS_DONE_OR_RETURN (sc, args); FFI_ARGS_DONE_OR_RETURN (sc, args);
FFI_RETURN_ERR (sc, gnupg_setenv (name, value, overwrite)); if (gnupg_setenv (name, value, overwrite))
FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
FFI_RETURN (sc);
} }
static pointer static pointer