Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a00c583

Browse files
committed
Make initdb's suggested "pg_ctl start" command line more reliable.
The original coding here was not nearly careful enough about quoting special characters, and it didn't get corner cases right for constructing the pg_ctl path either. Use join_path_components() and appendShellString() to do it honestly, so that the string will more likely work if blindly copied-and-pasted. While at it, teach appendShellString() not to quote strings that clearly don't need it, so that the output from initdb doesn't become uglier than it was before in typical cases where quoting is not needed. Ryan Murphy, reviewed by Michael Paquier and myself Discussion: <CAHeEsBeAe1FeBypT3E8R1ZVZU0e8xv3A-7BHg6bEOi=jZny2Uw@mail.gmail.com>
1 parent 6471045 commit a00c583

File tree

3 files changed

+46
-17
lines changed

3 files changed

+46
-17
lines changed

src/bin/initdb/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ include $(top_builddir)/src/Makefile.global
1818

1919
override CPPFLAGS := -DFRONTEND -I$(libpq_srcdir) -I$(top_srcdir)/src/timezone $(CPPFLAGS)
2020

21+
# note: we need libpq only because fe_utils does
22+
LDFLAGS += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
23+
2124
# use system timezone data?
2225
ifneq (,$(with_system_tzdata))
2326
override CPPFLAGS += '-DSYSTEMTZDIR="$(with_system_tzdata)"'

src/bin/initdb/initdb.c

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "getaddrinfo.h"
6868
#include "getopt_long.h"
6969
#include "miscadmin.h"
70+
#include "fe_utils/string_utils.h"
7071

7172

7273
/* Define PG_FLUSH_DATA_WORKS if we have an implementation for pg_flush_data */
@@ -331,14 +332,6 @@ do { \
331332
output_failed = true, output_errno = errno; \
332333
} while (0)
333334

334-
#ifndef WIN32
335-
#define QUOTE_PATH ""
336-
#define DIR_SEP "/"
337-
#else
338-
#define QUOTE_PATH "\""
339-
#define DIR_SEP "\\"
340-
#endif
341-
342335
static char *
343336
escape_quotes(const char *src)
344337
{
@@ -3359,7 +3352,8 @@ main(int argc, char *argv[])
33593352
int c;
33603353
int option_index;
33613354
char *effective_user;
3362-
char bin_dir[MAXPGPATH];
3355+
PQExpBuffer start_db_cmd;
3356+
char pg_ctl_path[MAXPGPATH];
33633357

33643358
/*
33653359
* Ensure that buffering behavior of stdout and stderr matches what it is
@@ -3587,14 +3581,33 @@ main(int argc, char *argv[])
35873581
if (authwarning != NULL)
35883582
fprintf(stderr, "%s", authwarning);
35893583

3590-
/* Get directory specification used to start this executable */
3591-
strlcpy(bin_dir, argv[0], sizeof(bin_dir));
3592-
get_parent_directory(bin_dir);
3584+
/*
3585+
* Build up a shell command to tell the user how to start the server
3586+
*/
3587+
start_db_cmd = createPQExpBuffer();
3588+
3589+
/* Get directory specification used to start initdb ... */
3590+
strlcpy(pg_ctl_path, argv[0], sizeof(pg_ctl_path));
3591+
canonicalize_path(pg_ctl_path);
3592+
get_parent_directory(pg_ctl_path);
3593+
/* ... and tag on pg_ctl instead */
3594+
join_path_components(pg_ctl_path, pg_ctl_path, "pg_ctl");
3595+
3596+
/* path to pg_ctl, properly quoted */
3597+
appendShellString(start_db_cmd, pg_ctl_path);
3598+
3599+
/* add -D switch, with properly quoted data directory */
3600+
appendPQExpBufferStr(start_db_cmd, " -D ");
3601+
appendShellString(start_db_cmd, pgdata_native);
3602+
3603+
/* add suggested -l switch and "start" command */
3604+
appendPQExpBufferStr(start_db_cmd, " -l logfile start");
35933605

35943606
printf(_("\nSuccess. You can now start the database server using:\n\n"
3595-
" %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
3596-
QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
3597-
QUOTE_PATH, pgdata_native, QUOTE_PATH);
3607+
" %s\n\n"),
3608+
start_db_cmd->data);
3609+
3610+
destroyPQExpBuffer(start_db_cmd);
35983611

35993612
return 0;
36003613
}

src/fe_utils/string_utils.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length,
418418

419419
/*
420420
* Append the given string to the shell command being built in the buffer,
421-
* with suitable shell-style quoting to create exactly one argument.
421+
* with shell-style quoting as needed to create exactly one argument.
422422
*
423423
* Forbid LF or CR characters, which have scant practical use beyond designing
424424
* security breaches. The Windows command shell is unusable as a conduit for
@@ -429,8 +429,22 @@ appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length,
429429
void
430430
appendShellString(PQExpBuffer buf, const char *str)
431431
{
432+
#ifdef WIN32
433+
int backslash_run_length = 0;
434+
#endif
432435
const char *p;
433436

437+
/*
438+
* Don't bother with adding quotes if the string is nonempty and clearly
439+
* contains only safe characters.
440+
*/
441+
if (*str != '\0' &&
442+
strspn(str, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_./:") == strlen(str))
443+
{
444+
appendPQExpBufferStr(buf, str);
445+
return;
446+
}
447+
434448
#ifndef WIN32
435449
appendPQExpBufferChar(buf, '\'');
436450
for (p = str; *p; p++)
@@ -450,7 +464,6 @@ appendShellString(PQExpBuffer buf, const char *str)
450464
}
451465
appendPQExpBufferChar(buf, '\'');
452466
#else /* WIN32 */
453-
int backslash_run_length = 0;
454467

455468
/*
456469
* A Windows system() argument experiences two layers of interpretation.

0 commit comments

Comments
 (0)