According to [1], windows does not support setenv, so for the patch to work
[3], would need to add it.
With the possibility of setenv going further [2], I am submitting in this
thread, the patch to add setenv support on the windows side, avoiding starting
a new trhead.
It is based on pre-existing functions, and seeks to correctly emulate the
functioning of the POSIX setenv, but has not yet been tested.
If this work is not acceptable then it is finished. And two memory leaks and a
possible access beyond heap bounds, reported and not fixed.
regards,
Ranier Vilela
[1] https://www.postgresql.org/message-id/29478.1576537771%40sss.pgh.pa.us
[2] https://www.postgresql.org/message-id/30119.1576538578%40sss.pgh.pa.us
[3]
https://www.postgresql.org/message-id/SN2PR05MB264066382E2CC75E734492C8E3510%40SN2PR05MB2640.namprd05.prod.outlook.com
diff --git a/src/common/exec.c b/src/common/exec.c
index 92dc3134a1..82e94b4df1 100644
--- a/src/common/exec.c
+++ b/src/common/exec.c
@@ -72,14 +72,15 @@ validate_exec(const char *path)
int is_x;
#ifdef WIN32
- char path_exe[MAXPGPATH + sizeof(".exe") - 1];
+ char path_exe[MAXPGPATH + sizeof(".exe")];
+ int path_len;
/* Win32 requires a .exe suffix for stat() */
- if (strlen(path) >= strlen(".exe") &&
- pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
+ path_len = strlen(path);
+ if (path_len >= (sizeof(".exe") - 1) &&
+ pg_strcasecmp(path + path_len - (sizeof(".exe") - 1), ".exe") != 0)
{
- strlcpy(path_exe, path, sizeof(path_exe) - 4);
- strcat(path_exe, ".exe");
+ snprintf(path_exe, sizeof(path_exe) - 5, "%s.exe", path);
path = path_exe;
}
#endif
@@ -566,11 +567,8 @@ set_pglocale_pgservice(const char *argv0, const char *app)
{
char path[MAXPGPATH];
char my_exec_path[MAXPGPATH];
- char env_path[MAXPGPATH + sizeof("PGSYSCONFDIR=")]; /* longer than
- * PGLOCALEDIR */
- char *dup_path;
- /* don't set LC_ALL in the backend */
+ /* don't set LC_ALL in the backend */
if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
{
setlocale(LC_ALL, "");
@@ -596,25 +594,19 @@ set_pglocale_pgservice(const char *argv0, const char *app)
if (getenv("PGLOCALEDIR") == NULL)
{
- /* set for libpq to use */
- snprintf(env_path, sizeof(env_path), "PGLOCALEDIR=%s", path);
- canonicalize_path(env_path + 12);
- dup_path = strdup(env_path);
- if (dup_path)
- putenv(dup_path);
+ /* set for libpq to use */
+ canonicalize_path(path);
+ setenv("PGLOCALEDIR", path, 1);
}
#endif
if (getenv("PGSYSCONFDIR") == NULL)
{
- get_etc_path(my_exec_path, path);
-
- /* set for libpq to use */
- snprintf(env_path, sizeof(env_path), "PGSYSCONFDIR=%s", path);
- canonicalize_path(env_path + 13);
- dup_path = strdup(env_path);
- if (dup_path)
- putenv(dup_path);
+ get_etc_path(my_exec_path, path);
+
+ /* set for libpq to use */
+ canonicalize_path(path);
+ setenv("PGSYSCONFDIR", path, 1);
}
}
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 275f3bb699..33dc9bf5ad 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -65,7 +65,7 @@ my @frontend_uselibpgcommon = (
my $frontend_extralibs = {
'initdb' => ['ws2_32.lib'],
'pg_restore' => ['ws2_32.lib'],
- 'pgbench' => ['ws2_32.lib'],
+ 'pgbench' => ['ws2_32.lib', 'bcrypt.lib'],
'psql' => ['ws2_32.lib']
};
my $frontend_extraincludes = {
@@ -184,6 +184,7 @@ sub mkvcbuild
$postgres->AddFiles('src/backend/utils/adt', 'jsonpath_scan.l',
'jsonpath_gram.y');
$postgres->AddDefine('BUILDING_DLL');
+ $postgres->AddLibrary('bcrypt.lib') if ($vsVersion > '12.00');
$postgres->AddLibrary('secur32.lib');
$postgres->AddLibrary('ws2_32.lib');
$postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
@@ -246,6 +247,7 @@ sub mkvcbuild
$libpq->AddDefine('FRONTEND');
$libpq->AddDefine('UNSAFE_STAT_OK');
$libpq->AddIncludeDir('src/port');
+ $libpq->AddLibrary('bcrypt.lib') if ($vsVersion > '12.00');
$libpq->AddLibrary('secur32.lib');
$libpq->AddLibrary('ws2_32.lib');
$libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
index c459a2417d..1ffddcceee 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -463,6 +463,7 @@ extern void _dosmaperr(unsigned long);
/* in port/win32env.c */
extern int pgwin32_putenv(const char *);
extern void pgwin32_unsetenv(const char *);
+extern int pgwin32_setenv(const char *name, const char *envval, int overwrite);
/* in port/win32security.c */
extern int pgwin32_is_service(void);
@@ -473,6 +474,7 @@ extern BOOL AddUserToTokenDacl(HANDLE hToken);
#define putenv(x) pgwin32_putenv(x)
#define unsetenv(x) pgwin32_unsetenv(x)
+#define setenv(n,v,o) pgwin32_setenv(n, v, o)
/* Things that exist in MinGW headers, but need to be added to MSVC */
#ifdef _MSC_VER
diff --git a/src/port/win32env.c b/src/port/win32env.c
index 6f4994c96a..e9845a78c8 100644
--- a/src/port/win32env.c
+++ b/src/port/win32env.c
@@ -123,3 +123,35 @@ pgwin32_unsetenv(const char *name)
pgwin32_putenv(envbuf);
free(envbuf);
}
+
+
+int
+pgwin32_setenv(const char *name, const char *envval, int overwrite)
+{
+ if (name == NULL)
+ return -1;
+
+ if (overwrite || !getenv(name)) {
+ char *envbuf;
+ int name_len;
+
+ name_len = strlen(name);
+ if (envval != NULL) {
+ envbuf = (char *) malloc(name_len + strlen(envval) + 2);
+ if (!envbuf)
+ return -1;
+
+ sprintf(envbuf, "%s=%s", name, envval);
+ } else {
+ envbuf = (char *) malloc(name_len + 2);
+ if (!envbuf)
+ return -1;
+
+ sprintf(envbuf, "%s=", name);
+ }
+ pgwin32_putenv(envbuf);
+ free(envbuf);
+ }
+
+ return 0;
+}