summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-11-29 18:34:22 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2013-11-29 18:34:22 -0500
commit4ab4e5c6bb04dc1fc747baed3d42d5aa2ea44dfa (patch)
treeb3ce5d354302872c5e99efd83e84e07ab4914d44
parentba63799598f134bad6f5a850dbca2549fa8b5146 (diff)
Fix assorted issues in pg_ctl's pgwin32_CommandLine().
Ensure that the invocation command for postgres or pg_ctl runservice double-quotes the executable's pathname; failure to do this leads to trouble when the path contains spaces. Also, ensure that the path ends in ".exe" in both cases and uses backslashes rather than slashes as directory separators. The latter issue is reported to confuse some third-party tools such as Symantec Backup Exec. Also, rewrite the function to avoid buffer overrun issues by using a PQExpBuffer instead of a fixed-size static buffer. Combinations of very long executable pathnames and very long data directory pathnames could have caused trouble before, for example. Back-patch to all active branches, since this code has been like this for a long while. Naoya Anzai and Tom Lane, reviewed by Rajeev Rastogi
-rw-r--r--src/bin/pg_ctl/pg_ctl.c74
1 files changed, 38 insertions, 36 deletions
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index d98530ceeee..8ad9812c1bf 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -18,7 +18,9 @@
#endif
#include "postgres_fe.h"
+
#include "libpq-fe.h"
+#include "pqexpbuffer.h"
#include <fcntl.h>
#include <locale.h>
@@ -1106,16 +1108,13 @@ pgwin32_IsInstalled(SC_HANDLE hSCM)
static char *
pgwin32_CommandLine(bool registration)
{
- static char cmdLine[MAXPGPATH];
+ PQExpBuffer cmdLine = createPQExpBuffer();
+ char cmdPath[MAXPGPATH];
int ret;
-#ifdef __CYGWIN__
- char buf[MAXPGPATH];
-#endif
-
if (registration)
{
- ret = find_my_exec(argv0, cmdLine);
+ ret = find_my_exec(argv0, cmdPath);
if (ret != 0)
{
write_stderr(_("%s: could not find own program executable\n"), progname);
@@ -1125,7 +1124,7 @@ pgwin32_CommandLine(bool registration)
else
{
ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
- cmdLine);
+ cmdPath);
if (ret != 0)
{
write_stderr(_("%s: could not find postgres program executable\n"), progname);
@@ -1135,54 +1134,57 @@ pgwin32_CommandLine(bool registration)
#ifdef __CYGWIN__
/* need to convert to windows path */
+ {
+ char buf[MAXPGPATH];
+
#if CYGWIN_VERSION_DLL_MAJOR >= 1007
- cygwin_conv_path(CCP_POSIX_TO_WIN_A, cmdLine, buf, sizeof(buf));
+ cygwin_conv_path(CCP_POSIX_TO_WIN_A, cmdPath, buf, sizeof(buf));
#else
- cygwin_conv_to_full_win32_path(cmdLine, buf);
+ cygwin_conv_to_full_win32_path(cmdPath, buf);
#endif
- strcpy(cmdLine, buf);
+ strcpy(cmdPath, buf);
+ }
#endif
+ /* if path does not end in .exe, append it */
+ if (strlen(cmdPath) < 4 ||
+ pg_strcasecmp(cmdPath + strlen(cmdPath) - 4, ".exe") != 0)
+ snprintf(cmdPath + strlen(cmdPath), sizeof(cmdPath) - strlen(cmdPath),
+ ".exe");
+
+ /* use backslashes in path to avoid problems with some third-party tools */
+ make_native_path(cmdPath);
+
+ /* be sure to double-quote the executable's name in the command */
+ appendPQExpBuffer(cmdLine, "\"%s\"", cmdPath);
+
+ /* append assorted switches to the command line, as needed */
+
if (registration)
- {
- if (pg_strcasecmp(cmdLine + strlen(cmdLine) - 4, ".exe"))
- {
- /* If commandline does not end in .exe, append it */
- strcat(cmdLine, ".exe");
- }
- strcat(cmdLine, " runservice -N \"");
- strcat(cmdLine, register_servicename);
- strcat(cmdLine, "\"");
- }
+ appendPQExpBuffer(cmdLine, " runservice -N \"%s\"",
+ register_servicename);
if (pg_data)
- {
- strcat(cmdLine, " -D \"");
- strcat(cmdLine, pg_data);
- strcat(cmdLine, "\"");
- }
+ appendPQExpBuffer(cmdLine, " -D \"%s\"", pg_data);
if (registration && do_wait)
- strcat(cmdLine, " -w");
+ appendPQExpBuffer(cmdLine, " -w");
if (registration && wait_seconds != DEFAULT_WAIT)
- /* concatenate */
- sprintf(cmdLine + strlen(cmdLine), " -t %d", wait_seconds);
+ appendPQExpBuffer(cmdLine, " -t %d", wait_seconds);
if (registration && silent_mode)
- strcat(cmdLine, " -s");
+ appendPQExpBuffer(cmdLine, " -s");
if (post_opts)
{
- strcat(cmdLine, " ");
- if (registration)
- strcat(cmdLine, " -o \"");
- strcat(cmdLine, post_opts);
if (registration)
- strcat(cmdLine, "\"");
+ appendPQExpBuffer(cmdLine, " -o \"%s\"", post_opts);
+ else
+ appendPQExpBuffer(cmdLine, " %s", post_opts);
}
- return cmdLine;
+ return cmdLine->data;
}
static void
@@ -1618,7 +1620,7 @@ CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_ser
*/
return r;
}
-#endif
+#endif /* defined(WIN32) || defined(__CYGWIN__) */
static void
do_advice(void)