diff options
author | Werner Koch <wk@gnupg.org> | 2017-11-28 12:34:12 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2017-11-28 13:10:30 +0100 |
commit | b67daca506991507cea9d383df7faf95117e58a6 (patch) | |
tree | 651968189278b3b7143e54d6bf6813c1bfece78e | |
parent | 97b0881216af24f2a46c11650e23691cff9cb12a (diff) | |
download | libgpg-error-b67daca506991507cea9d383df7faf95117e58a6.tar.gz |
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 <wk@gnupg.org>
-rw-r--r-- | src/gpg-error.def.in | 3 | ||||
-rw-r--r-- | src/gpg-error.h.in | 13 | ||||
-rw-r--r-- | src/gpg-error.vers | 3 | ||||
-rw-r--r-- | src/gpgrt-int.h | 8 | ||||
-rw-r--r-- | src/sysutils.c | 175 | ||||
-rw-r--r-- | src/visibility.c | 12 | ||||
-rw-r--r-- | src/visibility.h | 4 |
7 files changed, 218 insertions, 0 deletions
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index 5c7835f..6c40571 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -189,6 +189,9 @@ EXPORTS gpgrt_strdup @144 gpgrt_strconcat @145 + gpgrt_getenv @146 + gpgrt_setenv @147 + #ifdef HAVE_W32_SYSTEM gpgrt_w32_reg_query_string @148 #endif diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index 35027d6..3d9c914 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -445,6 +445,19 @@ char *gpgrt_strconcat (const char *s1, ...) GPGRT_ATTR_SENTINEL(0); void gpgrt_free (void *a); +/* + * System specific function wrappers. + */ + +/* A getenv replacement which mallocs the returned string. */ +char *gpgrt_getenv (const char *name); + +/* A setenv and a unsetenv replacement.*/ +int gpgrt_setenv (const char *name, const char *value, int overwrite); +#define gpgrt_unsetenv(n) gpgrt_setenv ((n), NULL, 1) + + + /* * Lock functions. diff --git a/src/gpg-error.vers b/src/gpg-error.vers index 074981b..661222c 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -163,6 +163,9 @@ GPG_ERROR_1.0 { gpgrt_strdup; gpgrt_strconcat; + gpgrt_getenv; + gpgrt_setenv; + local: *; }; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index c0e83b1..c65f630 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -559,6 +559,14 @@ int _gpgrt_logv_internal (int level, int ignore_arg_ptr, /* Return true if FD is valid. */ int _gpgrt_fd_valid_p (int fd); +/* A getenv variant which returns a malloced copy. */ +char *_gpgrt_getenv (const char *name); + +/* A setenv variant which can be used for unsetenv by setting VALUE to + * NULL and OVERRIDE to true. */ +int _gpgrt_setenv (const char *name, const char *value, int overwrite); + + /* 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*/ +} diff --git a/src/visibility.c b/src/visibility.c index 01ed2ce..45ac644 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -552,6 +552,18 @@ gpgrt_free (void *a) _gpgrt_free (a); } +char * +gpgrt_getenv (const char *name) +{ + return _gpgrt_getenv (name); +} + +int +gpgrt_setenv (const char *name, const char *value, int overwrite) +{ + return _gpgrt_setenv (name, value, overwrite); +} + int gpgrt_vfprintf (estream_t _GPGRT__RESTRICT stream, const char *_GPGRT__RESTRICT format, diff --git a/src/visibility.h b/src/visibility.h index 416f266..3c2d6be 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -124,6 +124,8 @@ MARK_VISIBLE (gpgrt_calloc) MARK_VISIBLE (gpgrt_strdup) MARK_VISIBLE (gpgrt_strconcat) MARK_VISIBLE (gpgrt_free) +MARK_VISIBLE (gpgrt_getenv) +MARK_VISIBLE (gpgrt_setenv) MARK_VISIBLE (gpgrt_fprintf) MARK_VISIBLE (gpgrt_fprintf_unlocked) MARK_VISIBLE (gpgrt_printf) @@ -268,6 +270,8 @@ MARK_VISIBLE (_gpgrt_log_assert) #define gpgrt_strdup _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_strconcat _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_free _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_getenv _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_setenv _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fprintf _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fprintf_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_printf _gpgrt_USE_UNDERSCORED_FUNCTION |