summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2017-11-28 12:34:12 +0100
committerWerner Koch <wk@gnupg.org>2017-11-28 13:10:30 +0100
commitb67daca506991507cea9d383df7faf95117e58a6 (patch)
tree651968189278b3b7143e54d6bf6813c1bfece78e
parent97b0881216af24f2a46c11650e23691cff9cb12a (diff)
downloadlibgpg-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.in3
-rw-r--r--src/gpg-error.h.in13
-rw-r--r--src/gpg-error.vers3
-rw-r--r--src/gpgrt-int.h8
-rw-r--r--src/sysutils.c175
-rw-r--r--src/visibility.c12
-rw-r--r--src/visibility.h4
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