Use setenv() in preference to putenv().

Since at least 2001 we've used putenv() and avoided setenv(), on the
grounds that the latter was unportable and not in POSIX.  However,
POSIX added it that same year, and by now the situation has reversed:
setenv() is probably more portable than putenv(), since POSIX now
treats the latter as not being a core function.  And setenv() has
cleaner semantics too.  So, let's reverse that old policy.

This commit adds a simple src/port/ implementation of setenv() for
any stragglers (we have one in the buildfarm, but I'd not be surprised
if that code is never used in the field).  More importantly, extend
win32env.c to also support setenv().  Then, replace usages of putenv()
with setenv(), and get rid of some ad-hoc implementations of setenv()
wannabees.

Also, adjust our src/port/ implementation of unsetenv() to follow the
POSIX spec that it returns an error indicator, rather than returning
void as per the ancient BSD convention.  I don't feel a need to make
all the call sites check for errors, but the portability stub ought
to match real-world practice.

Discussion: https://postgr.es/m/2065122.1609212051@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2020-12-30 12:55:59 -05:00
parent 62097a4cc8
commit 7ca37fb040
26 changed files with 234 additions and 199 deletions

19
configure vendored
View File

@ -15959,12 +15959,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

View File

@ -1757,11 +1757,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

View File

@ -1,8 +1,8 @@
-- Initialization that requires path substitution.
CREATE FUNCTION putenv(text)
CREATE FUNCTION setenv(text, text)
RETURNS void
AS '@libdir@/regress@DLSUFFIX@', 'regress_putenv'
AS '@libdir@/regress@DLSUFFIX@', 'regress_setenv'
LANGUAGE C STRICT;
CREATE FUNCTION wait_pid(int)
@ -11,4 +11,4 @@ CREATE FUNCTION wait_pid(int)
LANGUAGE C STRICT;
CREATE FUNCTION set_pgservicefile(text) RETURNS void LANGUAGE SQL
AS $$SELECT putenv('PGSERVICEFILE=@abs_srcdir@/' || $1)$$;
AS $$SELECT setenv('PGSERVICEFILE', '@abs_srcdir@/' || $1)$$;

View File

@ -1,11 +1,11 @@
-- Initialization that requires path substitution.
CREATE FUNCTION putenv(text)
CREATE FUNCTION setenv(text, text)
RETURNS void
AS '@libdir@/regress@DLSUFFIX@', 'regress_putenv'
AS '@libdir@/regress@DLSUFFIX@', 'regress_setenv'
LANGUAGE C STRICT;
CREATE FUNCTION wait_pid(int)
RETURNS void
AS '@libdir@/regress@DLSUFFIX@'
LANGUAGE C STRICT;
CREATE FUNCTION set_pgservicefile(text) RETURNS void LANGUAGE SQL
AS $$SELECT putenv('PGSERVICEFILE=@abs_srcdir@/' || $1)$$;
AS $$SELECT setenv('PGSERVICEFILE', '@abs_srcdir@/' || $1)$$;

View File

@ -105,20 +105,6 @@ char *localized_full_months[12 + 1];
static bool CurrentLocaleConvValid = false;
static bool CurrentLCTimeValid = false;
/* Environment variable storage area */
#define LC_ENV_BUFSIZE (NAMEDATALEN + 20)
static char lc_collate_envbuf[LC_ENV_BUFSIZE];
static char lc_ctype_envbuf[LC_ENV_BUFSIZE];
#ifdef LC_MESSAGES
static char lc_messages_envbuf[LC_ENV_BUFSIZE];
#endif
static char lc_monetary_envbuf[LC_ENV_BUFSIZE];
static char lc_numeric_envbuf[LC_ENV_BUFSIZE];
static char lc_time_envbuf[LC_ENV_BUFSIZE];
/* Cache for collation-related knowledge */
typedef struct
@ -163,7 +149,6 @@ pg_perm_setlocale(int category, const char *locale)
{
char *result;
const char *envvar;
char *envbuf;
#ifndef WIN32
result = setlocale(category, locale);
@ -199,7 +184,7 @@ pg_perm_setlocale(int category, const char *locale)
*/
if (category == LC_CTYPE)
{
static char save_lc_ctype[LC_ENV_BUFSIZE];
static char save_lc_ctype[NAMEDATALEN + 20];
/* copy setlocale() return value before callee invokes it again */
strlcpy(save_lc_ctype, result, sizeof(save_lc_ctype));
@ -216,16 +201,13 @@ pg_perm_setlocale(int category, const char *locale)
{
case LC_COLLATE:
envvar = "LC_COLLATE";
envbuf = lc_collate_envbuf;
break;
case LC_CTYPE:
envvar = "LC_CTYPE";
envbuf = lc_ctype_envbuf;
break;
#ifdef LC_MESSAGES
case LC_MESSAGES:
envvar = "LC_MESSAGES";
envbuf = lc_messages_envbuf;
#ifdef WIN32
result = IsoLocaleName(locale);
if (result == NULL)
@ -236,26 +218,19 @@ pg_perm_setlocale(int category, const char *locale)
#endif /* LC_MESSAGES */
case LC_MONETARY:
envvar = "LC_MONETARY";
envbuf = lc_monetary_envbuf;
break;
case LC_NUMERIC:
envvar = "LC_NUMERIC";
envbuf = lc_numeric_envbuf;
break;
case LC_TIME:
envvar = "LC_TIME";
envbuf = lc_time_envbuf;
break;
default:
elog(FATAL, "unrecognized LC category: %d", category);
envvar = NULL; /* keep compiler quiet */
envbuf = NULL;
return NULL;
return NULL; /* keep compiler quiet */
}
snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
if (putenv(envbuf))
if (setenv(envvar, result, 1) != 0)
return NULL;
return result;

View File

@ -2355,8 +2355,7 @@ check_need_password(const char *authmethodlocal, const char *authmethodhost)
void
setup_pgdata(void)
{
char *pgdata_get_env,
*pgdata_set_env;
char *pgdata_get_env;
if (!pg_data)
{
@ -2386,8 +2385,11 @@ setup_pgdata(void)
* need quotes otherwise on Windows because paths there are most likely to
* have embedded spaces.
*/
pgdata_set_env = psprintf("PGDATA=%s", pg_data);
putenv(pgdata_set_env);
if (setenv("PGDATA", pg_data, 1) != 0)
{
pg_log_error("could not set environment");
exit(1);
}
}

View File

@ -889,11 +889,10 @@ do_start(void)
*/
#ifndef WIN32
{
static char env_var[32];
char env_var[32];
snprintf(env_var, sizeof(env_var), "PG_GRANDPARENT_PID=%d",
(int) getppid());
putenv(env_var);
snprintf(env_var, sizeof(env_var), "%d", (int) getppid());
setenv("PG_GRANDPARENT_PID", env_var, 1);
}
#endif
@ -2340,12 +2339,10 @@ main(int argc, char **argv)
case 'D':
{
char *pgdata_D;
char *env_var;
pgdata_D = pg_strdup(optarg);
canonicalize_path(pgdata_D);
env_var = psprintf("PGDATA=%s", pgdata_D);
putenv(env_var);
setenv("PGDATA", pgdata_D, 1);
/*
* We could pass PGDATA just in an environment
@ -2353,6 +2350,7 @@ main(int argc, char **argv)
* 'ps' display
*/
pgdata_opt = psprintf("-D \"%s\" ", pgdata_D);
free(pgdata_D);
break;
}
case 'e':

View File

@ -97,20 +97,20 @@ get_control_data(ClusterInfo *cluster, bool live_check)
if (getenv("LC_MESSAGES"))
lc_messages = pg_strdup(getenv("LC_MESSAGES"));
pg_putenv("LC_COLLATE", NULL);
pg_putenv("LC_CTYPE", NULL);
pg_putenv("LC_MONETARY", NULL);
pg_putenv("LC_NUMERIC", NULL);
pg_putenv("LC_TIME", NULL);
unsetenv("LC_COLLATE");
unsetenv("LC_CTYPE");
unsetenv("LC_MONETARY");
unsetenv("LC_NUMERIC");
unsetenv("LC_TIME");
#ifndef WIN32
pg_putenv("LANG", NULL);
unsetenv("LANG");
#else
/* On Windows the default locale may not be English, so force it */
pg_putenv("LANG", "en");
setenv("LANG", "en", 1);
#endif
pg_putenv("LANGUAGE", NULL);
pg_putenv("LC_ALL", NULL);
pg_putenv("LC_MESSAGES", "C");
unsetenv("LANGUAGE");
unsetenv("LC_ALL");
setenv("LC_MESSAGES", "C", 1);
/*
* Check for clean shutdown
@ -490,17 +490,31 @@ get_control_data(ClusterInfo *cluster, bool live_check)
pclose(output);
/*
* Restore environment variables
* Restore environment variables. Note all but LANG and LC_MESSAGES were
* unset above.
*/
pg_putenv("LC_COLLATE", lc_collate);
pg_putenv("LC_CTYPE", lc_ctype);
pg_putenv("LC_MONETARY", lc_monetary);
pg_putenv("LC_NUMERIC", lc_numeric);
pg_putenv("LC_TIME", lc_time);
pg_putenv("LANG", lang);
pg_putenv("LANGUAGE", language);
pg_putenv("LC_ALL", lc_all);
pg_putenv("LC_MESSAGES", lc_messages);
if (lc_collate)
setenv("LC_COLLATE", lc_collate, 1);
if (lc_ctype)
setenv("LC_CTYPE", lc_ctype, 1);
if (lc_monetary)
setenv("LC_MONETARY", lc_monetary, 1);
if (lc_numeric)
setenv("LC_NUMERIC", lc_numeric, 1);
if (lc_time)
setenv("LC_TIME", lc_time, 1);
if (lang)
setenv("LANG", lang, 1);
else
unsetenv("LANG");
if (language)
setenv("LANGUAGE", language, 1);
if (lc_all)
setenv("LC_ALL", lc_all, 1);
if (lc_messages)
setenv("LC_MESSAGES", lc_messages, 1);
else
unsetenv("LC_MESSAGES");
pg_free(lc_collate);
pg_free(lc_ctype);

View File

@ -193,7 +193,7 @@ parseCommandLine(int argc, char *argv[])
* Push the user name into the environment so pre-9.1
* pg_ctl/libpq uses it.
*/
pg_putenv("PGUSER", os_info.user);
setenv("PGUSER", os_info.user, 1);
break;
case 'v':
@ -245,11 +245,11 @@ parseCommandLine(int argc, char *argv[])
char *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
getenv("PGOPTIONS"));
pg_putenv("PGOPTIONS", pgoptions);
setenv("PGOPTIONS", pgoptions, 1);
pfree(pgoptions);
}
else
pg_putenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY);
setenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY, 1);
/* Get values from env if not already set */
check_required_directory(&old_cluster.bindir, "PGBINOLD", false,

View File

@ -436,7 +436,6 @@ void end_progress_output(void);
void prep_status(const char *fmt,...) pg_attribute_printf(1, 2);
void check_ok(void);
unsigned int str2uint(const char *str);
void pg_putenv(const char *var, const char *val);
/* version.c */

View File

@ -241,39 +241,3 @@ str2uint(const char *str)
{
return strtoul(str, NULL, 10);
}
/*
* pg_putenv()
*
* This is like putenv(), but takes two arguments.
* It also does unsetenv() if val is NULL.
*/
void
pg_putenv(const char *var, const char *val)
{
if (val)
{
#ifndef WIN32
char *envstr;
envstr = psprintf("%s=%s", var, val);
putenv(envstr);
/*
* Do not free envstr because it becomes part of the environment on
* some operating systems. See port/unsetenv.c::unsetenv.
*/
#else
SetEnvironmentVariableA(var, val);
#endif
}
else
{
#ifndef WIN32
unsetenv(var);
#else
SetEnvironmentVariableA(var, "");
#endif
}
}

View File

@ -2296,17 +2296,8 @@ exec_command_setenv(PsqlScanState scan_state, bool active_branch,
else
{
/* Set variable to the value of the next argument */
char *newval;
newval = psprintf("%s=%s", envvar, envval);
putenv(newval);
setenv(envvar, envval, 1);
success = true;
/*
* Do not free newval here, it will screw up the environment if
* you do. See putenv man page for details. That means we leak a
* bit of memory here, but not enough to worry about.
*/
}
free(envvar);
free(envval);

View File

@ -435,9 +435,6 @@ 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 */
if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
@ -462,28 +459,15 @@ set_pglocale_pgservice(const char *argv0, const char *app)
get_locale_path(my_exec_path, path);
bindtextdomain(app, path);
textdomain(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, but don't override existing setting */
setenv("PGLOCALEDIR", path, 0);
#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);
setenv("PGSYSCONFDIR", path, 0);
}
}

View File

@ -171,7 +171,7 @@ get_restricted_token(void)
cmdline = pg_strdup(GetCommandLine());
putenv("PG_RESTRICT_EXEC=1");
setenv("PG_RESTRICT_EXEC", "1", 1);
if ((restrictedToken = CreateRestrictedProcess(cmdline, &pi)) == 0)
{

View File

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

View File

@ -447,8 +447,12 @@ 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);
extern int unsetenv(const char *name);
#endif
#ifndef HAVE_SRANDOM

View File

@ -490,7 +490,12 @@ 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 *value, int overwrite);
extern int pgwin32_unsetenv(const char *name);
#define putenv(x) pgwin32_putenv(x)
#define setenv(x,y,z) pgwin32_setenv(x,y,z)
#define unsetenv(x) pgwin32_unsetenv(x)
/* in port/win32security.c */
extern int pgwin32_is_service(void);
@ -499,9 +504,6 @@ extern int pgwin32_is_admin(void);
/* Windows security token manipulation (in src/common/exec.c) */
extern BOOL AddUserToTokenDacl(HANDLE hToken);
#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 */
#ifdef _MSC_VER

View File

@ -147,8 +147,9 @@ ecpg_start_test(const char *testname,
outfile_stdout,
outfile_stderr);
appnameenv = psprintf("PGAPPNAME=ecpg/%s", testname_dash.data);
putenv(appnameenv);
appnameenv = psprintf("ecpg/%s", testname_dash.data);
setenv("PGAPPNAME", appnameenv, 1);
free(appnameenv);
pid = spawn_process(cmd);
@ -160,7 +161,6 @@ ecpg_start_test(const char *testname,
}
unsetenv("PGAPPNAME");
free(appnameenv);
free(testname_dash.data);

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-2020, 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

@ -16,13 +16,20 @@
#include "c.h"
void
int
unsetenv(const char *name)
{
char *envstr;
/* Error conditions, per POSIX */
if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL)
{
errno = EINVAL;
return -1;
}
if (getenv(name) == NULL)
return; /* no work */
return 0; /* no work */
/*
* The technique embodied here works if libc follows the Single Unix Spec
@ -40,11 +47,12 @@ unsetenv(const char *name)
envstr = (char *) malloc(strlen(name) + 2);
if (!envstr) /* not much we can do if no memory */
return;
return -1;
/* Override the existing setting by forcibly defining the var */
sprintf(envstr, "%s=", name);
putenv(envstr);
if (putenv(envstr))
return -1;
/* Now we can clobber the variable definition this way: */
strcpy(envstr, "=");
@ -53,5 +61,5 @@ unsetenv(const char *name)
* This last putenv cleans up if we have multiple zero-length names as a
* result of unsetting multiple things.
*/
putenv(envstr);
return putenv(envstr);
}

View File

@ -1,8 +1,10 @@
/*-------------------------------------------------------------------------
*
* win32env.c
* putenv() and unsetenv() for win32, which update both process environment
* and caches in (potentially multiple) C run-time library (CRT) versions.
* putenv(), setenv(), and unsetenv() for win32.
*
* These functions update both the process environment and caches in
* (potentially multiple) C run-time library (CRT) versions.
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
@ -16,6 +18,11 @@
#include "c.h"
/*
* Note that unlike POSIX putenv(), this doesn't use the passed-in string
* as permanent storage.
*/
int
pgwin32_putenv(const char *envval)
{
@ -64,7 +71,7 @@ pgwin32_putenv(const char *envval)
}
*cp = '\0';
cp++;
if (strlen(cp))
if (*cp)
{
/*
* Only call SetEnvironmentVariable() when we are adding a variable,
@ -110,16 +117,47 @@ pgwin32_putenv(const char *envval)
return _putenv(envval);
}
void
int
pgwin32_setenv(const char *name, const char *value, int overwrite)
{
int res;
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;
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);
res = pgwin32_putenv(envstr);
free(envstr);
return res;
}
int
pgwin32_unsetenv(const char *name)
{
int res;
char *envbuf;
envbuf = (char *) malloc(strlen(name) + 2);
if (!envbuf)
return;
return -1;
sprintf(envbuf, "%s=", name);
pgwin32_putenv(envbuf);
res = pgwin32_putenv(envbuf);
free(envbuf);
return res;
}

View File

@ -98,8 +98,9 @@ isolation_start_test(const char *testname,
exit(2);
}
appnameenv = psprintf("PGAPPNAME=isolation/%s", testname);
putenv(appnameenv);
appnameenv = psprintf("isolation/%s", testname);
setenv("PGAPPNAME", appnameenv, 1);
free(appnameenv);
pid = spawn_process(psql_cmd);
@ -111,7 +112,6 @@ isolation_start_test(const char *testname,
}
unsetenv("PGAPPNAME");
free(appnameenv);
return pid;
}

View File

@ -724,18 +724,6 @@ get_expectfile(const char *testname, const char *file)
return NULL;
}
/*
* Handy subroutine for setting an environment variable "var" to "val"
*/
static void
doputenv(const char *var, const char *val)
{
char *s;
s = psprintf("%s=%s", var, val);
putenv(s);
}
/*
* Prepare environment variables for running regression tests
*/
@ -746,7 +734,7 @@ initialize_environment(void)
* Set default application_name. (The test_function may choose to
* override this, but if it doesn't, we have something useful in place.)
*/
putenv("PGAPPNAME=pg_regress");
setenv("PGAPPNAME", "pg_regress", 1);
if (nolocale)
{
@ -769,7 +757,7 @@ initialize_environment(void)
* variables unset; see PostmasterMain().
*/
#if defined(WIN32) || defined(__CYGWIN__) || defined(__darwin__)
putenv("LANG=C");
setenv("LANG", "C", 1);
#endif
}
@ -781,21 +769,21 @@ initialize_environment(void)
*/
unsetenv("LANGUAGE");
unsetenv("LC_ALL");
putenv("LC_MESSAGES=C");
setenv("LC_MESSAGES", "C", 1);
/*
* Set encoding as requested
*/
if (encoding)
doputenv("PGCLIENTENCODING", encoding);
setenv("PGCLIENTENCODING", encoding, 1);
else
unsetenv("PGCLIENTENCODING");
/*
* Set timezone and datestyle for datetime-related tests
*/
putenv("PGTZ=PST8PDT");
putenv("PGDATESTYLE=Postgres, MDY");
setenv("PGTZ", "PST8PDT", 1);
setenv("PGDATESTYLE", "Postgres, MDY", 1);
/*
* Likewise set intervalstyle to ensure consistent results. This is a bit
@ -809,9 +797,10 @@ initialize_environment(void)
if (!old_pgoptions)
old_pgoptions = "";
new_pgoptions = psprintf("PGOPTIONS=%s %s",
new_pgoptions = psprintf("%s %s",
old_pgoptions, my_pgoptions);
putenv(new_pgoptions);
setenv("PGOPTIONS", new_pgoptions, 1);
free(new_pgoptions);
}
if (temp_instance)
@ -832,17 +821,17 @@ initialize_environment(void)
unsetenv("PGDATA");
#ifdef HAVE_UNIX_SOCKETS
if (hostname != NULL)
doputenv("PGHOST", hostname);
setenv("PGHOST", hostname, 1);
else
{
sockdir = getenv("PG_REGRESS_SOCK_DIR");
if (!sockdir)
sockdir = make_temp_sockdir();
doputenv("PGHOST", sockdir);
setenv("PGHOST", sockdir, 1);
}
#else
Assert(hostname != NULL);
doputenv("PGHOST", hostname);
setenv("PGHOST", hostname, 1);
#endif
unsetenv("PGHOSTADDR");
if (port != -1)
@ -850,7 +839,7 @@ initialize_environment(void)
char s[16];
sprintf(s, "%d", port);
doputenv("PGPORT", s);
setenv("PGPORT", s, 1);
}
}
else
@ -864,7 +853,7 @@ initialize_environment(void)
*/
if (hostname != NULL)
{
doputenv("PGHOST", hostname);
setenv("PGHOST", hostname, 1);
unsetenv("PGHOSTADDR");
}
if (port != -1)
@ -872,10 +861,10 @@ initialize_environment(void)
char s[16];
sprintf(s, "%d", port);
doputenv("PGPORT", s);
setenv("PGPORT", s, 1);
}
if (user != NULL)
doputenv("PGUSER", user);
setenv("PGUSER", user, 1);
/*
* However, we *don't* honor PGDATABASE, since we certainly don't wish
@ -2431,7 +2420,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
fprintf(stderr, _("port %d apparently in use, trying %d\n"), port, port + 1);
port++;
sprintf(s, "%d", port);
doputenv("PGPORT", s);
setenv("PGPORT", s, 1);
}
else
break;

View File

@ -91,8 +91,9 @@ psql_start_test(const char *testname,
exit(2);
}
appnameenv = psprintf("PGAPPNAME=pg_regress/%s", testname);
putenv(appnameenv);
appnameenv = psprintf("pg_regress/%s", testname);
setenv("PGAPPNAME", appnameenv, 1);
free(appnameenv);
pid = spawn_process(psql_cmd);
@ -104,7 +105,6 @@ psql_start_test(const char *testname,
}
unsetenv("PGAPPNAME");
free(appnameenv);
return pid;
}

View File

@ -624,22 +624,18 @@ make_tuple_indirect(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(newtup->t_data);
}
PG_FUNCTION_INFO_V1(regress_putenv);
PG_FUNCTION_INFO_V1(regress_setenv);
Datum
regress_putenv(PG_FUNCTION_ARGS)
regress_setenv(PG_FUNCTION_ARGS)
{
MemoryContext oldcontext;
char *envbuf;
char *envvar = text_to_cstring(PG_GETARG_TEXT_PP(0));
char *envval = text_to_cstring(PG_GETARG_TEXT_PP(1));
if (!superuser())
elog(ERROR, "must be superuser to change environment variables");
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
envbuf = text_to_cstring((text *) PG_GETARG_POINTER(0));
MemoryContextSwitchTo(oldcontext);
if (putenv(envbuf) != 0)
if (setenv(envvar, envval, 1) != 0)
elog(ERROR, "could not set environment variable: %m");
PG_RETURN_VOID();

View File

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