aboutsummaryrefslogtreecommitdiffstats
path: root/src/sysutils.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2017-11-28 11:34:12 +0000
committerWerner Koch <[email protected]>2017-11-28 12:10:30 +0000
commitb67daca506991507cea9d383df7faf95117e58a6 (patch)
tree651968189278b3b7143e54d6bf6813c1bfece78e /src/sysutils.c
parentcore: Install new files gpgrt.m4 and gpgrt-config. (diff)
downloadlibgpg-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.c175
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*/
+}