Skip to content

Commit 6c19bd9

Browse files
committed
Allow pg_upgrade to honor libpq environment variables. Add 'local'
checks for PGHOST and PGHOSTADDR.
1 parent 78b66cf commit 6c19bd9

File tree

7 files changed

+141
-130
lines changed

7 files changed

+141
-130
lines changed

contrib/pg_upgrade/controldata.c

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
#include <ctype.h>
1313

14-
static void putenv2(const char *var, const char *val);
15-
1614
/*
1715
* get_control_data()
1816
*
@@ -85,21 +83,21 @@ get_control_data(ClusterInfo *cluster, bool live_check)
8583
if (getenv("LC_MESSAGES"))
8684
lc_messages = pg_strdup(getenv("LC_MESSAGES"));
8785

88-
putenv2("LC_COLLATE", NULL);
89-
putenv2("LC_CTYPE", NULL);
90-
putenv2("LC_MONETARY", NULL);
91-
putenv2("LC_NUMERIC", NULL);
92-
putenv2("LC_TIME", NULL);
93-
putenv2("LANG",
86+
pg_putenv("LC_COLLATE", NULL);
87+
pg_putenv("LC_CTYPE", NULL);
88+
pg_putenv("LC_MONETARY", NULL);
89+
pg_putenv("LC_NUMERIC", NULL);
90+
pg_putenv("LC_TIME", NULL);
91+
pg_putenv("LANG",
9492
#ifndef WIN32
9593
NULL);
9694
#else
9795
/* On Windows the default locale cannot be English, so force it */
9896
"en");
9997
#endif
100-
putenv2("LANGUAGE", NULL);
101-
putenv2("LC_ALL", NULL);
102-
putenv2("LC_MESSAGES", "C");
98+
pg_putenv("LANGUAGE", NULL);
99+
pg_putenv("LC_ALL", NULL);
100+
pg_putenv("LC_MESSAGES", "C");
103101

104102
snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE,
105103
cluster->bindir,
@@ -374,15 +372,15 @@ get_control_data(ClusterInfo *cluster, bool live_check)
374372
/*
375373
* Restore environment variables
376374
*/
377-
putenv2("LC_COLLATE", lc_collate);
378-
putenv2("LC_CTYPE", lc_ctype);
379-
putenv2("LC_MONETARY", lc_monetary);
380-
putenv2("LC_NUMERIC", lc_numeric);
381-
putenv2("LC_TIME", lc_time);
382-
putenv2("LANG", lang);
383-
putenv2("LANGUAGE", language);
384-
putenv2("LC_ALL", lc_all);
385-
putenv2("LC_MESSAGES", lc_messages);
375+
pg_putenv("LC_COLLATE", lc_collate);
376+
pg_putenv("LC_CTYPE", lc_ctype);
377+
pg_putenv("LC_MONETARY", lc_monetary);
378+
pg_putenv("LC_NUMERIC", lc_numeric);
379+
pg_putenv("LC_TIME", lc_time);
380+
pg_putenv("LANG", lang);
381+
pg_putenv("LANGUAGE", language);
382+
pg_putenv("LC_ALL", lc_all);
383+
pg_putenv("LC_MESSAGES", lc_messages);
386384

387385
pg_free(lc_collate);
388386
pg_free(lc_ctype);
@@ -529,40 +527,3 @@ rename_old_pg_control(void)
529527
pg_log(PG_FATAL, "Unable to rename %s to %s.\n", old_path, new_path);
530528
check_ok();
531529
}
532-
533-
534-
/*
535-
* putenv2()
536-
*
537-
* This is like putenv(), but takes two arguments.
538-
* It also does unsetenv() if val is NULL.
539-
*/
540-
static void
541-
putenv2(const char *var, const char *val)
542-
{
543-
if (val)
544-
{
545-
#ifndef WIN32
546-
char *envstr = (char *) pg_malloc(strlen(var) +
547-
strlen(val) + 2);
548-
549-
sprintf(envstr, "%s=%s", var, val);
550-
putenv(envstr);
551-
552-
/*
553-
* Do not free envstr because it becomes part of the environment on
554-
* some operating systems. See port/unsetenv.c::unsetenv.
555-
*/
556-
#else
557-
SetEnvironmentVariableA(var, val);
558-
#endif
559-
}
560-
else
561-
{
562-
#ifndef WIN32
563-
unsetenv(var);
564-
#else
565-
SetEnvironmentVariableA(var, "");
566-
#endif
567-
}
568-
}

contrib/pg_upgrade/option.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,24 @@ parseCommandLine(int argc, char *argv[])
5353
};
5454
int option; /* Command line option */
5555
int optindex = 0; /* used by getopt_long */
56-
int user_id;
56+
int os_user_effective_id;
5757

58-
if (getenv("PGUSER"))
59-
{
60-
pg_free(os_info.user);
61-
os_info.user = pg_strdup(getenv("PGUSER"));
62-
}
58+
user_opts.transfer_mode = TRANSFER_MODE_COPY;
6359

6460
os_info.progname = get_progname(argv[0]);
61+
62+
/* Process libpq env. variables; load values here for usage() output */
6563
old_cluster.port = getenv("PGPORT") ? atoi(getenv("PGPORT")) : DEF_PGPORT;
6664
new_cluster.port = getenv("PGPORT") ? atoi(getenv("PGPORT")) : DEF_PGPORT;
67-
/* must save value, getenv()'s pointer is not stable */
6865

69-
user_opts.transfer_mode = TRANSFER_MODE_COPY;
70-
71-
/* user lookup and 'root' test must be split because of usage() */
72-
user_id = get_user_info(&os_info.user);
66+
os_user_effective_id = get_user_info(&os_info.user);
67+
/* we override just the database user name; we got the OS id above */
68+
if (getenv("PGUSER"))
69+
{
70+
pg_free(os_info.user);
71+
/* must save value, getenv()'s pointer is not stable */
72+
os_info.user = pg_strdup(getenv("PGUSER"));
73+
}
7374

7475
if (argc > 1)
7576
{
@@ -86,7 +87,8 @@ parseCommandLine(int argc, char *argv[])
8687
}
8788
}
8889

89-
if (user_id == 0)
90+
/* Allow help and version to be run as root, so do the test here. */
91+
if (os_user_effective_id == 0)
9092
pg_log(PG_FATAL, "%s: cannot be run as root\n", os_info.progname);
9193

9294
getcwd(os_info.cwd, MAXPGPATH);
@@ -96,14 +98,6 @@ parseCommandLine(int argc, char *argv[])
9698
{
9799
switch (option)
98100
{
99-
case 'd':
100-
old_cluster.pgdata = pg_strdup(optarg);
101-
break;
102-
103-
case 'D':
104-
new_cluster.pgdata = pg_strdup(optarg);
105-
break;
106-
107101
case 'b':
108102
old_cluster.bindir = pg_strdup(optarg);
109103
break;
@@ -116,6 +110,14 @@ parseCommandLine(int argc, char *argv[])
116110
user_opts.check = true;
117111
break;
118112

113+
case 'd':
114+
old_cluster.pgdata = pg_strdup(optarg);
115+
break;
116+
117+
case 'D':
118+
new_cluster.pgdata = pg_strdup(optarg);
119+
break;
120+
119121
case 'g':
120122
pg_log(PG_REPORT, "Running in debug mode\n");
121123
log_opts.debug = true;
@@ -156,6 +158,11 @@ parseCommandLine(int argc, char *argv[])
156158
case 'u':
157159
pg_free(os_info.user);
158160
os_info.user = pg_strdup(optarg);
161+
/*
162+
* Push the user name into the environment so pre-9.1
163+
* pg_ctl/libpq uses it.
164+
*/
165+
pg_putenv("PGUSER", os_info.user);
159166
break;
160167

161168
case 'v':
@@ -197,14 +204,14 @@ parseCommandLine(int argc, char *argv[])
197204
}
198205

199206
/* Get values from env if not already set */
200-
validateDirectoryOption(&old_cluster.pgdata, "OLDDATADIR", "-d",
201-
"old cluster data resides");
202-
validateDirectoryOption(&new_cluster.pgdata, "NEWDATADIR", "-D",
203-
"new cluster data resides");
204207
validateDirectoryOption(&old_cluster.bindir, "OLDBINDIR", "-b",
205208
"old cluster binaries reside");
206209
validateDirectoryOption(&new_cluster.bindir, "NEWBINDIR", "-B",
207210
"new cluster binaries reside");
211+
validateDirectoryOption(&old_cluster.pgdata, "OLDDATADIR", "-d",
212+
"old cluster data resides");
213+
validateDirectoryOption(&new_cluster.pgdata, "NEWDATADIR", "-D",
214+
"new cluster data resides");
208215

209216
get_pkglibdirs();
210217
}

contrib/pg_upgrade/pg_upgrade.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ setup(char *argv0, bool live_check)
149149
* make sure the user has a clean environment, otherwise, we may confuse
150150
* libpq when we connect to one (or both) of the servers.
151151
*/
152-
check_for_libpq_envvars();
152+
check_pghost_envvar();
153153

154154
verify_directories();
155155

contrib/pg_upgrade/pg_upgrade.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ PGresult *executeQueryOrDie(PGconn *conn, const char *fmt,...);
361361
void start_postmaster(ClusterInfo *cluster);
362362
void stop_postmaster(bool fast);
363363
uint32 get_major_server_version(ClusterInfo *cluster);
364-
void check_for_libpq_envvars(void);
364+
void check_pghost_envvar(void);
365365

366366

367367
/* util.c */
@@ -378,6 +378,7 @@ void *pg_malloc(int size);
378378
void pg_free(void *ptr);
379379
const char *getErrorText(int errNum);
380380
unsigned int str2uint(const char *str);
381+
void pg_putenv(const char *var, const char *val);
381382

382383

383384
/* version.c */

contrib/pg_upgrade/server.c

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ start_postmaster(ClusterInfo *cluster)
145145
char cmd[MAXPGPATH];
146146
PGconn *conn;
147147
bool exit_hook_registered = false;
148+
int pg_ctl_return = 0;
148149
#ifndef WIN32
149150
char *output_filename = log_opts.filename;
150151
#else
@@ -183,7 +184,11 @@ start_postmaster(ClusterInfo *cluster)
183184
"-c autovacuum=off -c autovacuum_freeze_max_age=2000000000",
184185
log_opts.filename);
185186

186-
exec_prog(true, "%s", cmd);
187+
/*
188+
* Don't throw an error right away, let connecting throw the error
189+
* because it might supply a reason for the failure.
190+
*/
191+
pg_ctl_return = exec_prog(false, "%s", cmd);
187192

188193
/* Check to see if we can connect to the server; if not, report it. */
189194
if ((conn = get_db_conn(cluster, "template1")) == NULL ||
@@ -198,6 +203,11 @@ start_postmaster(ClusterInfo *cluster)
198203
}
199204
PQfinish(conn);
200205

206+
/* If the connection didn't fail, fail now */
207+
if (pg_ctl_return != 0)
208+
pg_log(PG_FATAL, "pg_ctl failed to start the %s server\n",
209+
CLUSTER_NAME(cluster));
210+
201211
os_info.running_cluster = cluster;
202212
}
203213

@@ -241,50 +251,37 @@ stop_postmaster(bool fast)
241251

242252

243253
/*
244-
* check_for_libpq_envvars()
254+
* check_pghost_envvar()
245255
*
246-
* tests whether any libpq environment variables are set.
247-
* Since pg_upgrade connects to both the old and the new server,
248-
* it is potentially dangerous to have any of these set.
249-
*
250-
* If any are found, will log them and cancel.
256+
* Tests that PGHOST does not point to a non-local server
251257
*/
252258
void
253-
check_for_libpq_envvars(void)
259+
check_pghost_envvar(void)
254260
{
255261
PQconninfoOption *option;
256262
PQconninfoOption *start;
257-
bool found = false;
258263

259264
/* Get valid libpq env vars from the PQconndefaults function */
260265

261266
start = PQconndefaults();
262267

263268
for (option = start; option->keyword != NULL; option++)
264269
{
265-
if (option->envvar)
270+
if (option->envvar && (strcmp(option->envvar, "PGHOST") == 0 ||
271+
strcmp(option->envvar, "PGHOSTADDR") == 0))
266272
{
267-
const char *value;
268-
269-
/* This allows us to see error messages in the local encoding */
270-
if (strcmp(option->envvar, "PGCLIENTENCODING") == 0)
271-
continue;
272-
273-
value = getenv(option->envvar);
274-
if (value && strlen(value) > 0)
275-
{
276-
found = true;
277-
278-
pg_log(PG_WARNING,
279-
"libpq env var %-20s is currently set to: %s\n", option->envvar, value);
280-
}
273+
const char *value = getenv(option->envvar);
274+
275+
if (value && strlen(value) > 0 &&
276+
/* check for 'local' host values */
277+
(strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
278+
strcmp(value, "::1") != 0 && value[0] != '/'))
279+
pg_log(PG_FATAL,
280+
"libpq environment variable %s has a non-local server value: %s\n",
281+
option->envvar, value);
281282
}
282283
}
283284

284285
/* Free the memory that libpq allocated on our behalf */
285286
PQconninfoFree(start);
286-
287-
if (found)
288-
pg_log(PG_FATAL,
289-
"libpq env vars have been found and listed above, please unset them for pg_upgrade\n");
290287
}

contrib/pg_upgrade/util.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,41 @@ str2uint(const char *str)
244244
{
245245
return strtoul(str, NULL, 10);
246246
}
247+
248+
249+
/*
250+
* pg_putenv()
251+
*
252+
* This is like putenv(), but takes two arguments.
253+
* It also does unsetenv() if val is NULL.
254+
*/
255+
void
256+
pg_putenv(const char *var, const char *val)
257+
{
258+
if (val)
259+
{
260+
#ifndef WIN32
261+
char *envstr = (char *) pg_malloc(strlen(var) +
262+
strlen(val) + 2);
263+
264+
sprintf(envstr, "%s=%s", var, val);
265+
putenv(envstr);
266+
267+
/*
268+
* Do not free envstr because it becomes part of the environment on
269+
* some operating systems. See port/unsetenv.c::unsetenv.
270+
*/
271+
#else
272+
SetEnvironmentVariableA(var, val);
273+
#endif
274+
}
275+
else
276+
{
277+
#ifndef WIN32
278+
unsetenv(var);
279+
#else
280+
SetEnvironmentVariableA(var, "");
281+
#endif
282+
}
283+
}
284+

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy