Add fallback implementation for setenv()

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
This commit is contained in:
Michael Paquier 2021-06-01 09:27:31 +09:00
parent 6f9e7f21fd
commit 02037af3ff
8 changed files with 82 additions and 3 deletions

19
configure vendored
View File

@ -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

View 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

View File

@ -495,6 +495,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

View File

@ -371,6 +371,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. */
#define HAVE_SETENV 1
/* Define to 1 if you have the `setproctitle' function. */
/* #undef HAVE_SETPROCTITLE */

View 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

View 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 */

48
src/port/setenv.c Normal file
View File

@ -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);
}

View 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);