diff --git a/configure b/configure index cbbaf77e3f..a774a7c7f1 100755 --- a/configure +++ b/configure @@ -15858,12 +15858,29 @@ case $host_os in # Windows uses a specialised env handler mingw*) +$as_echo "#define HAVE_SETENV 1" >>confdefs.h + + $as_echo "#define HAVE_UNSETENV 1" >>confdefs.h + ac_cv_func_setenv=yes ac_cv_func_unsetenv=yes ;; *) - ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" + ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv" +if test "x$ac_cv_func_setenv" = xyes; then : + $as_echo "#define HAVE_SETENV 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" setenv.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS setenv.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" if test "x$ac_cv_func_unsetenv" = xyes; then : $as_echo "#define HAVE_UNSETENV 1" >>confdefs.h diff --git a/configure.in b/configure.in index 14a6be6748..8a124a3817 100644 --- a/configure.in +++ b/configure.in @@ -1747,11 +1747,13 @@ fi case $host_os in # Windows uses a specialised env handler mingw*) + AC_DEFINE(HAVE_SETENV, 1, [Define to 1 because replacement version used.]) AC_DEFINE(HAVE_UNSETENV, 1, [Define to 1 because replacement version used.]) + ac_cv_func_setenv=yes ac_cv_func_unsetenv=yes ;; *) - AC_REPLACE_FUNCS([unsetenv]) + AC_REPLACE_FUNCS([setenv unsetenv]) ;; esac diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index c199cd46d2..2fdf6ad289 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -473,6 +473,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SECURITY_PAM_APPL_H +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + /* Define to 1 if you have the `setproctitle' function. */ #undef HAVE_SETPROCTITLE diff --git a/src/include/port.h b/src/include/port.h index 271ff0d00b..d4c94a4411 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -429,6 +429,10 @@ extern size_t strnlen(const char *str, size_t maxlen); extern long random(void); #endif +#ifndef HAVE_SETENV +extern int setenv(const char *name, const char *value, int overwrite); +#endif + #ifndef HAVE_UNSETENV extern void unsetenv(const char *name); #endif diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h index 8b6576b23d..6c0f788ab4 100644 --- a/src/include/port/win32_port.h +++ b/src/include/port/win32_port.h @@ -462,6 +462,7 @@ extern void _dosmaperr(unsigned long); /* in port/win32env.c */ extern int pgwin32_putenv(const char *); +extern int pgwin32_setenv(const char *name, const char *value, int overwrite); extern void pgwin32_unsetenv(const char *); /* in port/win32security.c */ @@ -472,6 +473,7 @@ extern int pgwin32_is_admin(void); extern BOOL AddUserToTokenDacl(HANDLE hToken); #define putenv(x) pgwin32_putenv(x) +#define setenv(x,y,z) pgwin32_setenv(x,y,z) #define unsetenv(x) pgwin32_unsetenv(x) /* Things that exist in MinGW headers, but need to be added to MSVC */ diff --git a/src/port/setenv.c b/src/port/setenv.c new file mode 100644 index 0000000000..440bc832ce --- /dev/null +++ b/src/port/setenv.c @@ -0,0 +1,48 @@ +/*------------------------------------------------------------------------- + * + * setenv.c + * setenv() emulation for machines without it + * + * Portions Copyright (c) 1996-2021, 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/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 20da7985c1..a8195a4930 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -101,7 +101,7 @@ sub mkvcbuild dirent.c dlopen.c getopt.c getopt_long.c link.c pread.c pwrite.c pg_bitutils.c pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c - pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c + pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c setenv.c system.c sprompt.c strerror.c tar.c thread.c win32env.c win32error.c win32security.c win32setlocale.c); diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index 38ddf09f65..7f533b5ccf 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -341,6 +341,7 @@ sub GenerateFiles HAVE_RL_FILENAME_QUOTING_FUNCTION => undef, HAVE_RL_RESET_SCREEN_SIZE => undef, HAVE_SECURITY_PAM_APPL_H => undef, + HAVE_SETENV => undef, HAVE_SETPROCTITLE => undef, HAVE_SETPROCTITLE_FAST => undef, HAVE_SETSID => undef,