Make win32 builds always do SetEnvironmentVariable() when doing putenv().

Also, if linked against other versions than the default MSVCRT library
(for example the MSVC build which links against MSVCRT80), also update
the cache in the default MSVCRT at the same time.

This should fix the issues with setting LC_MESSAGES on the MSVC build.

Original patch from Hiroshi Inoue and Hiroshi Saito, much rewritten
by me.
This commit is contained in:
Magnus Hagander 2009-01-21 10:30:02 +00:00
parent fa40ca42a6
commit 0154345078
6 changed files with 175 additions and 20 deletions

6
configure vendored
View File

@ -17919,6 +17919,12 @@ case " $LIBOBJS " in
;; ;;
esac esac
case " $LIBOBJS " in
*" win32env.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS win32env.$ac_objext"
;;
esac
case " $LIBOBJS " in case " $LIBOBJS " in
*" win32error.$ac_objext "* ) ;; *" win32error.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS win32error.$ac_objext" *) LIBOBJS="$LIBOBJS win32error.$ac_objext"

View File

@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
dnl $PostgreSQL: pgsql/configure.in,v 1.587 2009/01/14 18:10:21 momjian Exp $ dnl $PostgreSQL: pgsql/configure.in,v 1.588 2009/01/21 10:30:02 mha Exp $
dnl dnl
dnl Developers, please strive to achieve this order: dnl Developers, please strive to achieve this order:
dnl dnl
@ -1274,6 +1274,7 @@ AC_REPLACE_FUNCS(gettimeofday)
AC_LIBOBJ(kill) AC_LIBOBJ(kill)
AC_LIBOBJ(open) AC_LIBOBJ(open)
AC_LIBOBJ(rand) AC_LIBOBJ(rand)
AC_LIBOBJ(win32env)
AC_LIBOBJ(win32error) AC_LIBOBJ(win32error)
AC_DEFINE([HAVE_SYMLINK], 1, AC_DEFINE([HAVE_SYMLINK], 1,
[Define to 1 if you have the `symlink' function.]) [Define to 1 if you have the `symlink' function.])

View File

@ -4,7 +4,7 @@
* *
* Portions Copyright (c) 2002-2009, PostgreSQL Global Development Group * Portions Copyright (c) 2002-2009, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.45 2009/01/09 14:07:00 mha Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.46 2009/01/21 10:30:02 mha Exp $
* *
*----------------------------------------------------------------------- *-----------------------------------------------------------------------
*/ */
@ -55,6 +55,9 @@
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/pg_locale.h" #include "utils/pg_locale.h"
#ifdef WIN32
#include <shlwapi.h>
#endif
#define MAX_L10N_DATA 80 #define MAX_L10N_DATA 80
@ -89,6 +92,10 @@ static char lc_monetary_envbuf[LC_ENV_BUFSIZE];
static char lc_numeric_envbuf[LC_ENV_BUFSIZE]; static char lc_numeric_envbuf[LC_ENV_BUFSIZE];
static char lc_time_envbuf[LC_ENV_BUFSIZE]; static char lc_time_envbuf[LC_ENV_BUFSIZE];
#ifdef WIN32
static char *IsoLocaleName(const char *); /* MSVC specific */
#endif
/* /*
* pg_perm_setlocale * pg_perm_setlocale
@ -148,8 +155,13 @@ pg_perm_setlocale(int category, const char *locale)
case LC_MESSAGES: case LC_MESSAGES:
envvar = "LC_MESSAGES"; envvar = "LC_MESSAGES";
envbuf = lc_messages_envbuf; envbuf = lc_messages_envbuf;
#ifdef WIN32
result = IsoLocaleName(locale);
if (result == NULL)
result = locale;
#endif /* WIN32 */
break; break;
#endif #endif /* LC_MESSAGES */
case LC_MONETARY: case LC_MONETARY:
envvar = "LC_MONETARY"; envvar = "LC_MONETARY";
envbuf = lc_monetary_envbuf; envbuf = lc_monetary_envbuf;
@ -166,25 +178,13 @@ pg_perm_setlocale(int category, const char *locale)
elog(FATAL, "unrecognized LC category: %d", category); elog(FATAL, "unrecognized LC category: %d", category);
envvar = NULL; /* keep compiler quiet */ envvar = NULL; /* keep compiler quiet */
envbuf = NULL; envbuf = NULL;
break; return NULL;
} }
snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result); snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
#ifndef WIN32
if (putenv(envbuf)) if (putenv(envbuf))
return NULL; return NULL;
#else
/*
* On Windows, we need to modify both the process environment and the
* cached version in msvcrt
*/
if (!SetEnvironmentVariable(envvar, result))
return NULL;
if (_putenv(envbuf))
return NULL;
#endif
return result; return result;
} }
@ -599,3 +599,53 @@ cache_locale_time(void)
CurrentLCTimeValid = true; CurrentLCTimeValid = true;
} }
#ifdef WIN32
/*
* Convert Windows locale name to the ISO formatted one
* if possible.
*
* This function returns NULL if conversion is impossible,
* otherwise returns the pointer to a static area which
* contains the iso formatted locale name.
*/
static
char *IsoLocaleName(const char *winlocname)
{
#if (_MSC_VER >= 1400) /* VC8.0 or later */
static char iso_lc_messages[32];
_locale_t loct = NULL;
if (pg_strcasecmp("c", winlocname) == 0 ||
pg_strcasecmp("posix", winlocname) == 0)
{
strcpy(iso_lc_messages, "C");
return iso_lc_messages;
}
loct = _create_locale(LC_CTYPE, winlocname);
if (loct != NULL)
{
char isolang[32], isocrty[32];
LCID lcid;
lcid = loct->locinfo->lc_handle[LC_CTYPE];
if (lcid == 0)
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
_free_locale(loct);
if (!GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, isolang, sizeof(isolang)))
return NULL;
if (!GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, isocrty, sizeof(isocrty)))'
return NULL;
snprintf(iso_lc_messages, sizeof(iso_lc_messages) - 1, "%s_%s", isolang, isocrty);
return iso_lc_messages;
}
return NULL;
#else
return NULL; /* Not supported on this version of msvc/mingw */
#endif /* _MSC_VER >= 1400 */
}
#endif /* WIN32 */

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.85 2009/01/07 03:39:33 momjian Exp $ */ /* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.86 2009/01/21 10:30:02 mha Exp $ */
#if defined(_MSC_VER) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__BORLANDC__)
#define WIN32_ONLY_COMPILER #define WIN32_ONLY_COMPILER
@ -291,6 +291,11 @@ extern int pgwin32_is_service(void);
/* in port/win32error.c */ /* in port/win32error.c */
extern void _dosmaperr(unsigned long); extern void _dosmaperr(unsigned long);
/* in port/win32env.c */
extern int pgwin32_putenv(const char *);
extern void pgwin32_unsetenv(const char *);
#define putenv(x) pgwin32_putenv(x)
#define unsetenv(x) pgwin32_unsetenv(x)
/* Things that exist in MingW headers, but need to be added to MSVC */ /* Things that exist in MingW headers, but need to be added to MSVC */
#ifdef WIN32_ONLY_COMPILER #ifdef WIN32_ONLY_COMPILER

93
src/port/win32env.c Normal file
View File

@ -0,0 +1,93 @@
/*-------------------------------------------------------------------------
*
* win32env.c
* putenv() and unsetenv() for win32, that updates both process
* environment and the cached versions in (potentially multiple)
* MSVCRT.
*
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/port/win32env.c,v 1.1 2009/01/21 10:30:02 mha Exp $
*
*-------------------------------------------------------------------------
*/
#include "c.h"
int
pgwin32_putenv(const char *envval)
{
char *envcpy;
char *cp;
/*
* Each version of MSVCRT has its own _putenv() call in the runtime
* library.
*
* If we're in VC 7.0 or later (means != mingw), update in
* the 6.0 MSVCRT.DLL environment as well, to work with third party
* libraries linked against it (such as gnuwin32 libraries).
*/
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
typedef int (_cdecl *PUTENVPROC)(const char *);
HMODULE hmodule;
static PUTENVPROC putenvFunc = NULL;
int ret;
if (putenvFunc == NULL)
{
hmodule = GetModuleHandle("msvcrt");
if (hmodule == NULL)
return 1;
putenvFunc = (PUTENVPROC)GetProcAddress(hmodule, "_putenv");
if (putenvFunc == NULL)
return 1;
}
ret = putenvFunc(envval);
if (ret != 0)
return ret;
#endif /* _MSC_VER >= 1300 */
/*
* Update the process environment - to make modifications visible
* to child processes.
*
* Need a copy of the string so we can modify it.
*/
envcpy = strdup(envval);
cp = strchr(envcpy, '=');
if (cp == NULL)
return -1;
*cp = '\0';
cp++;
if (strlen(cp) == 0)
cp = NULL;
if (!SetEnvironmentVariable(envcpy, cp))
{
free(envcpy);
return -1;
}
free(envcpy);
/* Finally, update our "own" cache */
return _putenv(envval);
}
void
pgwin32_unsetenv(const char *name)
{
char *envbuf;
envbuf = (char *) malloc(strlen(name)+2);
if (!envbuf)
return;
sprintf(envbuf, "%s=", name);
pgwin32_putenv(envbuf);
free(envbuf);
}

View File

@ -3,7 +3,7 @@ package Mkvcbuild;
# #
# Package that generates build files for msvc build # Package that generates build files for msvc build
# #
# $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.35 2008/12/20 22:04:02 mha Exp $ # $PostgreSQL: pgsql/src/tools/msvc/Mkvcbuild.pm,v 1.36 2009/01/21 10:30:02 mha Exp $
# #
use Carp; use Carp;
use Win32; use Win32;
@ -44,10 +44,10 @@ sub mkvcbuild
our @pgportfiles = qw( our @pgportfiles = qw(
chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c
unsetenv.c getaddrinfo.c gettimeofday.c kill.c open.c rand.c getaddrinfo.c gettimeofday.c kill.c open.c rand.c
snprintf.c strlcat.c strlcpy.c copydir.c dirmod.c exec.c noblock.c path.c pipe.c snprintf.c strlcat.c strlcpy.c copydir.c dirmod.c exec.c noblock.c path.c pipe.c
pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c sprompt.c thread.c pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c sprompt.c thread.c
getopt.c getopt_long.c dirent.c rint.c win32error.c); getopt.c getopt_long.c dirent.c rint.c win32env.c win32error.c);
$libpgport = $solution->AddProject('libpgport','lib','misc'); $libpgport = $solution->AddProject('libpgport','lib','misc');
$libpgport->AddDefine('FRONTEND'); $libpgport->AddDefine('FRONTEND');