On Sat, May 29, 2021 at 10:44:14AM -0400, Tom Lane wrote:
> What I had in mind was to *only* add pgwin32_setenv, not setenv.c.
> There's no evidence that any other modern platform lacks setenv.
> Moreover, there's no issue in these branches unless your platform
> lacks setenv yet has GSS support.

I have been finally able to poke at that, resulting in the attached.
You are right that adding only the fallback implementation for
setenv() seems to be enough.  I cannot get my environment to complain,
and the code compiles.
--
Michael
From 9dfda72db16d7ee0752acc4010bfb74a6c0c80e5 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Mon, 31 May 2021 09:13:07 +0900
Subject: [PATCH] Add fallback implementation for setenv()

---
 src/include/pg_config.h.in    |  3 +++
 src/include/port.h            |  4 +++
 src/include/port/win32_port.h |  2 ++
 src/port/Makefile             |  1 +
 src/port/setenv.c             | 48 +++++++++++++++++++++++++++++++++++
 configure                     | 19 +++++++++++++-
 configure.in                  |  4 ++-
 src/tools/msvc/Mkvcbuild.pm   |  2 +-
 src/tools/msvc/Solution.pm    |  1 +
 9 files changed, 81 insertions(+), 3 deletions(-)
 create mode 100644 src/port/setenv.c

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 <security/pam_appl.h> 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/Makefile b/src/port/Makefile
index 8defa1257b..21c88d70b3 100644
--- a/src/port/Makefile
+++ b/src/port/Makefile
@@ -54,6 +54,7 @@ OBJS = \
 	qsort.o \
 	qsort_arg.o \
 	quotes.o \
+	setenv.o \
 	snprintf.o \
 	sprompt.o \
 	strerror.o \
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/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/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,
-- 
2.32.0.rc0

Attachment: signature.asc
Description: PGP signature

Reply via email to