diff --git a/configure b/configure index d3582f56b8..b28620fbef 100755 --- a/configure +++ b/configure @@ -16183,15 +16183,32 @@ case $host_os in # Unix sockets. mingw*) +$as_echo "#define HAVE_SETENV 1" >>confdefs.h + + $as_echo "#define HAVE_UNSETENV 1" >>confdefs.h $as_echo "#define HAVE_GETPEEREID 1" >>confdefs.h + ac_cv_func_setenv=yes ac_cv_func_unsetenv=yes ac_cv_func_getpeereid=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 bc07e92f8f..2cb6cda654 100644 --- a/configure.in +++ b/configure.in @@ -1788,12 +1788,14 @@ case $host_os in # and doesn't need a replacement getpeereid because it doesn't use # Unix sockets. 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_DEFINE(HAVE_GETPEEREID, 1, [Define to 1 because function not required.]) + ac_cv_func_setenv=yes ac_cv_func_unsetenv=yes ac_cv_func_getpeereid=yes;; *) - AC_REPLACE_FUNCS([unsetenv getpeereid]) + AC_REPLACE_FUNCS([setenv unsetenv getpeereid]) ;; esac diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 244886a531..9ac86d1c0a 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -495,6 +495,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/pg_config.h.win32 b/src/include/pg_config.h.win32 index 2fc4be5f14..e4590cf2e5 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -371,6 +371,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. */ +#define HAVE_SETENV 1 + /* 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 ebcee1c55c..8a5c6389e6 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -437,6 +437,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 f4841fb397..f9daaf66d7 100644 --- a/src/include/port/win32_port.h +++ b/src/include/port/win32_port.h @@ -471,6 +471,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 */ @@ -481,6 +482,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 b13e57fa53..131a4c76c4 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -100,7 +100,7 @@ sub mkvcbuild dirent.c dlopen.c getopt.c getopt_long.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);