Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Add fallback implementation for setenv()
authorMichael Paquier <michael@paquier.xyz>
Tue, 1 Jun 2021 00:27:31 +0000 (09:27 +0900)
committerMichael Paquier <michael@paquier.xyz>
Tue, 1 Jun 2021 00:27:31 +0000 (09:27 +0900)
This fixes the code compilation on Windows with MSVC and Kerberos, as
a missing implementation of setenv() causes a compilation failure of the
GSSAPI code.  This was only reproducible when building the code with
Kerberos, something that buildfarm animal hamerkop has fixed recently.

This issue only happens on 12 and 13, as this code has been introduced
in b0b39f7.  HEAD is already able to compile properly thanks to
7ca37fb0, and this commit is a minimal cherry-pick of it.

Thanks to Tom Lane for the discussion.

Discussion: https://postgr.es/m/YLDtm5WGjPxm6ua4@paquier.xyz
Backpatch-through: 12

configure
configure.in
src/include/pg_config.h.in
src/include/pg_config.h.win32
src/include/port.h
src/include/port/win32_port.h
src/port/setenv.c [new file with mode: 0644]
src/tools/msvc/Mkvcbuild.pm

index d3582f56b88a11e0f20f76b6badd364277b65b16..b28620fbef2f3cb0bf653318c9693e0d75f1084c 100755 (executable)
--- 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
 
index bc07e92f8fbccc5a5230753e7abb4a0848f5fcd3..2cb6cda654ffa3809c6ea285df6b2333df272c96 100644 (file)
@@ -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
 
index 244886a5314dfe147bc684eab565ebf90c71cd85..9ac86d1c0a27e9e98b7697bedfd7fb48f3c936d3 100644 (file)
 /* 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
 
index 2fc4be5f14cb3c067cea0d43eb38d253861d00ad..e4590cf2e5a62d510dce5fe4e0d23464ded608ff 100644 (file)
 /* 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. */
+#define HAVE_SETENV 1
+
 /* Define to 1 if you have the `setproctitle' function. */
 /* #undef HAVE_SETPROCTITLE */
 
index ebcee1c55cf89986cd9c8a0d9ede855c84519e32..8a5c6389e6fa5e3bc62e05cd4d638aea6e24cb0c 100644 (file)
@@ -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
index f4841fb3975d49749629c83dc20a17e064d48270..f9daaf66d7f994b6d2c2ee2175caf7572b09423b 100644 (file)
@@ -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 (file)
index 0000000..440bc83
--- /dev/null
@@ -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);
+}
index b13e57fa53193332df3fae80dd1b9892715f96d4..131a4c76c4f5e6747b953ac0518f745289149760 100644 (file)
@@ -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);