diff options
Diffstat (limited to 'src/port')
-rw-r--r-- | src/port/setenv.c | 48 | ||||
-rw-r--r-- | src/port/unsetenv.c | 18 | ||||
-rw-r--r-- | src/port/win32env.c | 50 |
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; } |