diff options
author | Werner Koch <[email protected]> | 2017-11-28 11:34:12 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2017-11-28 12:10:30 +0000 |
commit | b67daca506991507cea9d383df7faf95117e58a6 (patch) | |
tree | 651968189278b3b7143e54d6bf6813c1bfece78e /src/sysutils.c | |
parent | core: Install new files gpgrt.m4 and gpgrt-config. (diff) | |
download | libgpg-error-b67daca506991507cea9d383df7faf95117e58a6.tar.gz libgpg-error-b67daca506991507cea9d383df7faf95117e58a6.zip |
core: New API functions gpgrt_getenv and gpgrt_setenv.
* src/gpg-error.h.in (gpgrt_getenv, gpgrt_setenv): New.
(gpgrt_unsetenv): New macro.
* src/gpg-error.vers, src/gpg-error.def.in: Add them.
* src/visibility.c (gpgrt_getenv, gpgrt_setenv): New.
* src/visibility.h: Add them.
* src/sysutils.c: Include string.h and on Windows windows.h.
(_gpgrt_getenv): New.
(_gpgrt_setenv): New.
--
These functions are wrappers to cope with Windows problems. The code
is similar to what we have in GnuPG but not identical.
Requires better testing.
Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'src/sysutils.c')
-rw-r--r-- | src/sysutils.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/sysutils.c b/src/sysutils.c index 1933506..2dda4cd 100644 --- a/src/sysutils.c +++ b/src/sysutils.c @@ -21,7 +21,12 @@ #include <config.h> #include <stdlib.h> #include <stdint.h> +#include <string.h> #include <unistd.h> +#include <errno.h> +#ifdef HAVE_W32_SYSTEM +# include <windows.h> +#endif #include "gpgrt-int.h" @@ -37,3 +42,173 @@ _gpgrt_fd_valid_p (int fd) close (d); return 1; } + + +/* Our variant of getenv. The returned string must be freed. If the + * environment variable does not exists NULL is retruned and ERRNO set + * to 0. */ +char * +_gpgrt_getenv (const char *name) +{ + if (!name || !*name || strchr (name, '=')) + { + _gpg_err_set_errno (EINVAL); + return NULL; + } + +#ifdef HAVE_W32_SYSTEM + { + int len, size; + char *result; + + len = GetEnvironmentVariable (name, NULL, 0); + if (!len && GetLastError () == ERROR_ENVVAR_NOT_FOUND) + { + _gpg_err_set_errno (0); + return NULL; + } + again: + size = len; + result = _gpgrt_malloc (size); + if (!result) + return NULL; + len = GetEnvironmentVariable (name, result, size); + if (len >= size) + { + /* Changed in the meantime - retry. */ + _gpgrt_free (result); + goto again; + } + if (!len && GetLastError () == ERROR_ENVVAR_NOT_FOUND) + { + /* Deleted in the meantime. */ + _gpgrt_free (result); + _gpg_err_set_errno (0); + return NULL; + } + if (!len) + { + /* Other error. FIXME: We need mapping fucntion. */ + _gpgrt_free (result); + _gpg_err_set_errno (EIO); + return NULL; + } + + return result; + } +#else /*!HAVE_W32_SYSTEM*/ + { + const char *s = getenv (name); + if (!s) + { + _gpg_err_set_errno (0); + return NULL; + } + return _gpgrt_strdup (s); + } +#endif /*!HAVE_W32_SYSTEM*/ +} + + +/* Wrapper around setenv so that we can have the same function in + * Windows and Unix. In contrast to the standard setenv passing a + * VALUE as NULL and setting OVERWRITE will remove the envvar. */ +int +_gpgrt_setenv (const char *name, const char *value, int overwrite) +{ + if (!name || !*name || strchr (name, '=')) + { + _gpg_err_set_errno (EINVAL); + return -1; + } + +#ifdef 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. Note that gpgrt_getenv ignores the libc + * values - however, too much existing code still uses getenv. */ + { + int exists; + char tmpbuf[10]; + char *buf; + + if (!value && overwrite) + { + if (!SetEnvironmentVariable (name, NULL)) + { + _gpg_err_set_errno (EINVAL); + return -1; + } + if (getenv (name)) + { + /* Ugly: Leaking memory. */ + buf = _gpgrt_strdup (name); + if (!buf) + return -1; + return putenv (buf); + } + return 0; + } + + exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf); + if ((! exists || overwrite) && !SetEnvironmentVariable (name, value)) + { + _gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */ + return -1; + } + if (overwrite || !getenv (name)) + { + /* Ugly: Leaking memory. */ + buf = _gpgrt_strconcat (name, "=", value, NULL); + if (!buf) + return -1; + return putenv (buf); + } + return 0; + } + +#else /*!HAVE_W32_SYSTEM*/ + +# ifdef HAVE_SETENV + + { + if (!value && overwrite) + return unsetenv (name); + else + return setenv (name, value, overwrite); + } + +# else /*!HAVE_SETENV*/ + +# if __GNUC__ +# warning no setenv - using putenv but leaking memory. +# endif + { + char *buf; + + if (!value && overwrite) + { + if (getenv (name)) + { + buf = _gpgrt_strdup (name); + if (!buf) + return -1; + return putenv (buf); + } + } + else if (overwrite || !getenv (name)) + { + buf = _gpgrt_strconcat (name, "=", value, NULL); + if (!buf) + return -1; + return putenv (buf); + } + + return 0; + } +# endif /*!HAVE_SETENV*/ +#endif /*!HAVE_W32_SYSTEM*/ +} |