summaryrefslogtreecommitdiff
path: root/src/port
diff options
context:
space:
mode:
Diffstat (limited to 'src/port')
-rw-r--r--src/port/setenv.c48
-rw-r--r--src/port/unsetenv.c18
-rw-r--r--src/port/win32env.c50
3 files changed, 105 insertions, 11 deletions
diff --git a/src/port/setenv.c b/src/port/setenv.c
new file mode 100644
index 0000000000..d8a5647fb0
--- /dev/null
+++ b/src/port/setenv.c
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * setenv.c
+ * setenv() emulation for machines without it
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/setenv.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+
+int
+setenv(const char *name, const char *value, int overwrite)
+{
+ char *envstr;
+
+ /* Error conditions, per POSIX */
+ if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL ||
+ value == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* No work if variable exists and we're not to replace it */
+ if (overwrite == 0 && getenv(name) != NULL)
+ return 0;
+
+ /*
+ * Add or replace the value using putenv(). This will leak memory if the
+ * same variable is repeatedly redefined, but there's little we can do
+ * about that when sitting atop putenv().
+ */
+ envstr = (char *) malloc(strlen(name) + strlen(value) + 2);
+ if (!envstr) /* not much we can do if no memory */
+ return -1;
+
+ sprintf(envstr, "%s=%s", name, value);
+
+ return putenv(envstr);
+}
diff --git a/src/port/unsetenv.c b/src/port/unsetenv.c
index f2028c2f83..a5f19f8db3 100644
--- a/src/port/unsetenv.c
+++ b/src/port/unsetenv.c
@@ -16,13 +16,20 @@
#include "c.h"
-void
+int
unsetenv(const char *name)
{
char *envstr;
+ /* Error conditions, per POSIX */
+ if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
if (getenv(name) == NULL)
- return; /* no work */
+ return 0; /* no work */
/*
* The technique embodied here works if libc follows the Single Unix Spec
@@ -40,11 +47,12 @@ unsetenv(const char *name)
envstr = (char *) malloc(strlen(name) + 2);
if (!envstr) /* not much we can do if no memory */
- return;
+ return -1;
/* Override the existing setting by forcibly defining the var */
sprintf(envstr, "%s=", name);
- putenv(envstr);
+ if (putenv(envstr))
+ return -1;
/* Now we can clobber the variable definition this way: */
strcpy(envstr, "=");
@@ -53,5 +61,5 @@ unsetenv(const char *name)
* This last putenv cleans up if we have multiple zero-length names as a
* result of unsetting multiple things.
*/
- putenv(envstr);
+ return putenv(envstr);
}
diff --git a/src/port/win32env.c b/src/port/win32env.c
index 177488cc67..f5bed67297 100644
--- a/src/port/win32env.c
+++ b/src/port/win32env.c
@@ -1,8 +1,10 @@
/*-------------------------------------------------------------------------
*
* win32env.c
- * putenv() and unsetenv() for win32, which update both process environment
- * and caches in (potentially multiple) C run-time library (CRT) versions.
+ * putenv(), setenv(), and unsetenv() for win32.
+ *
+ * These functions update both the process environment and caches in
+ * (potentially multiple) C run-time library (CRT) versions.
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
@@ -16,6 +18,11 @@
#include "c.h"
+
+/*
+ * Note that unlike POSIX putenv(), this doesn't use the passed-in string
+ * as permanent storage.
+ */
int
pgwin32_putenv(const char *envval)
{
@@ -64,7 +71,7 @@ pgwin32_putenv(const char *envval)
}
*cp = '\0';
cp++;
- if (strlen(cp))
+ if (*cp)
{
/*
* Only call SetEnvironmentVariable() when we are adding a variable,
@@ -110,16 +117,47 @@ pgwin32_putenv(const char *envval)
return _putenv(envval);
}
-void
+int
+pgwin32_setenv(const char *name, const char *value, int overwrite)
+{
+ int res;
+ char *envstr;
+
+ /* Error conditions, per POSIX */
+ if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL ||
+ value == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* No work if variable exists and we're not to replace it */
+ if (overwrite == 0 && getenv(name) != NULL)
+ return 0;
+
+ envstr = (char *) malloc(strlen(name) + strlen(value) + 2);
+ if (!envstr) /* not much we can do if no memory */
+ return -1;
+
+ sprintf(envstr, "%s=%s", name, value);
+
+ res = pgwin32_putenv(envstr);
+ free(envstr);
+ return res;
+}
+
+int
pgwin32_unsetenv(const char *name)
{
+ int res;
char *envbuf;
envbuf = (char *) malloc(strlen(name) + 2);
if (!envbuf)
- return;
+ return -1;
sprintf(envbuf, "%s=", name);
- pgwin32_putenv(envbuf);
+ res = pgwin32_putenv(envbuf);
free(envbuf);
+ return res;
}