aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in1
-rw-r--r--contrib/pg_upgrade/check.c2
-rw-r--r--contrib/pg_upgrade/controldata.c2
-rw-r--r--contrib/pg_upgrade/exec.c4
-rw-r--r--src/bin/initdb/initdb.c40
-rw-r--r--src/bin/pg_ctl/pg_ctl.c14
-rw-r--r--src/bin/pg_dump/pg_dumpall.c4
-rw-r--r--src/bin/psql/command.c6
-rw-r--r--src/include/port.h45
-rw-r--r--src/interfaces/ecpg/test/pg_regress_ecpg.c2
-rw-r--r--src/interfaces/libpq/Makefile6
-rw-r--r--src/interfaces/libpq/bcc32.mak7
-rw-r--r--src/interfaces/libpq/win32.mak7
-rw-r--r--src/port/system.c117
-rw-r--r--src/test/isolation/isolation_main.c2
-rw-r--r--src/test/regress/pg_regress.c26
-rw-r--r--src/test/regress/pg_regress_main.c2
-rw-r--r--src/tools/msvc/Mkvcbuild.pm2
18 files changed, 196 insertions, 93 deletions
diff --git a/configure.in b/configure.in
index fc9c52f83d2..52357a6bba3 100644
--- a/configure.in
+++ b/configure.in
@@ -1353,6 +1353,7 @@ if test "$PORTNAME" = "win32"; then
AC_REPLACE_FUNCS(gettimeofday)
AC_LIBOBJ(kill)
AC_LIBOBJ(open)
+ AC_LIBOBJ(system)
AC_LIBOBJ(win32env)
AC_LIBOBJ(win32error)
AC_LIBOBJ(win32setlocale)
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 56e912d8c3d..d22b6d38e29 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -970,7 +970,7 @@ get_bin_version(ClusterInfo *cluster)
int pre_dot,
post_dot;
- snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" --version" SYSTEMQUOTE, cluster->bindir);
+ snprintf(cmd, sizeof(cmd), "\"%s/pg_ctl\" --version", cluster->bindir);
if ((output = popen(cmd, "r")) == NULL ||
fgets(cmd_output, sizeof(cmd_output), output) == NULL)
diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
index fa0a0053bab..476c6be276e 100644
--- a/contrib/pg_upgrade/controldata.c
+++ b/contrib/pg_upgrade/controldata.c
@@ -110,7 +110,7 @@ get_control_data(ClusterInfo *cluster, bool live_check)
pg_putenv("LC_ALL", NULL);
pg_putenv("LC_MESSAGES", "C");
- snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE,
+ snprintf(cmd, sizeof(cmd), "\"%s/%s \"%s\"",
cluster->bindir,
live_check ? "pg_controldata\"" : "pg_resetxlog\" -n",
cluster->pgdata);
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 7f013013a06..91e66e6ecf4 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -59,14 +59,14 @@ static DWORD mainThreadId = 0;
mainThreadId = GetCurrentThreadId();
#endif
- written = strlcpy(cmd, SYSTEMQUOTE, sizeof(cmd));
+ written = 0;
va_start(ap, fmt);
written += vsnprintf(cmd + written, MAXCMDLEN - written, fmt, ap);
va_end(ap);
if (written >= MAXCMDLEN)
pg_fatal("command too long\n");
written += snprintf(cmd + written, MAXCMDLEN - written,
- " >> \"%s\" 2>&1" SYSTEMQUOTE, log_file);
+ " >> \"%s\" 2>&1", log_file);
if (written >= MAXCMDLEN)
pg_fatal("command too long\n");
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index b53fa8bd088..83b7f6e24d8 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1130,11 +1130,11 @@ test_config_settings(void)
test_buffs = MIN_BUFS_FOR_CONNS(test_conns);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" --boot -x0 %s "
+ "\"%s\" --boot -x0 %s "
"-c max_connections=%d "
"-c shared_buffers=%d "
"-c dynamic_shared_memory_type=none "
- "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+ "< \"%s\" > \"%s\" 2>&1",
backend_exec, boot_options,
test_conns, test_buffs,
DEVNULL, DEVNULL);
@@ -1165,11 +1165,11 @@ test_config_settings(void)
}
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" --boot -x0 %s "
+ "\"%s\" --boot -x0 %s "
"-c max_connections=%d "
"-c shared_buffers=%d "
"-c dynamic_shared_memory_type=none "
- "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+ "< \"%s\" > \"%s\" 2>&1",
backend_exec, boot_options,
n_connections, test_buffs,
DEVNULL, DEVNULL);
@@ -1503,7 +1503,7 @@ bootstrap_template1(void)
unsetenv("PGCLIENTENCODING");
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" --boot -x1 %s %s %s" SYSTEMQUOTE,
+ "\"%s\" --boot -x1 %s %s %s",
backend_exec,
data_checksums ? "-k" : "",
boot_options, talkargs);
@@ -1544,7 +1544,7 @@ setup_auth(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -1622,7 +1622,7 @@ get_set_pwd(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -1722,7 +1722,7 @@ setup_depend(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -1755,7 +1755,7 @@ setup_sysviews(void)
* We use -j here to avoid backslashing stuff in system_views.sql
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s -j template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s -j template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -1786,7 +1786,7 @@ setup_description(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -1893,7 +1893,7 @@ setup_collation(void)
#if defined(HAVE_LOCALE_T) && !defined(WIN32)
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2038,7 +2038,7 @@ setup_conversion(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2076,7 +2076,7 @@ setup_dictionary(void)
* We use -j here to avoid backslashing stuff
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s -j template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s -j template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2127,7 +2127,7 @@ setup_privileges(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2190,7 +2190,7 @@ setup_schema(void)
* We use -j here to avoid backslashing stuff in information_schema.sql
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s -j template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s -j template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2207,7 +2207,7 @@ setup_schema(void)
PG_CMD_CLOSE;
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2241,7 +2241,7 @@ load_plpgsql(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2266,7 +2266,7 @@ vacuum_db(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2322,7 +2322,7 @@ make_template0(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
@@ -2354,7 +2354,7 @@ make_postgres(void)
fflush(stdout);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" %s template1 >%s" SYSTEMQUOTE,
+ "\"%s\" %s template1 >%s",
backend_exec, backend_options,
DEVNULL);
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index fc87e7d76ed..473d6534064 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -435,11 +435,11 @@ start_postmaster(void)
* the PID without having to rely on reading it back from the pidfile.
*/
if (log_file != NULL)
- snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &",
exec_path, pgdata_opt, post_opts,
DEVNULL, log_file);
else
- snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1 &" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "\"%s\" %s%s < \"%s\" 2>&1 &",
exec_path, pgdata_opt, post_opts, DEVNULL);
return system(cmd);
@@ -453,10 +453,10 @@ start_postmaster(void)
PROCESS_INFORMATION pi;
if (log_file != NULL)
- snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "CMD /C \"\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1\"",
exec_path, pgdata_opt, post_opts, DEVNULL, log_file);
else
- snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "CMD /C \"\"%s\" %s%s < \"%s\" 2>&1\"",
exec_path, pgdata_opt, post_opts, DEVNULL);
if (!CreateRestrictedProcess(cmd, &pi, false))
@@ -814,10 +814,10 @@ do_init(void)
post_opts = "";
if (!silent_mode)
- snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "\"%s\" %s%s",
exec_path, pgdata_opt, post_opts);
else
- snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s > \"%s\"" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "\"%s\" %s%s > \"%s\"",
exec_path, pgdata_opt, post_opts, DEVNULL);
if (system(cmd) != 0)
@@ -2035,7 +2035,7 @@ adjust_data_dir(void)
my_exec_path = pg_strdup(exec_path);
/* it's important for -C to be the first option, see main.c */
- snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" -C data_directory %s%s" SYSTEMQUOTE,
+ snprintf(cmd, MAXPGPATH, "\"%s\" -C data_directory %s%s",
my_exec_path,
pgdata_opt ? pgdata_opt : "",
post_opts ? post_opts : "");
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 47fe6ccc07f..208e49bbcd0 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -1666,7 +1666,7 @@ runPgDump(const char *dbname)
PQExpBuffer cmd = createPQExpBuffer();
int ret;
- appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s", pg_dump_bin,
+ appendPQExpBuffer(cmd, "\"%s\" %s", pg_dump_bin,
pgdumpopts->data);
/*
@@ -1687,8 +1687,6 @@ runPgDump(const char *dbname)
doShellQuoting(cmd, connstrbuf->data);
- appendPQExpBufferStr(cmd, SYSTEMQUOTE);
-
if (verbose)
fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index fd64ba824f1..dabcd680fff 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1936,10 +1936,10 @@ editFile(const char *fname, int lineno)
editorName, fname);
#else
if (lineno > 0)
- sys = psprintf(SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
+ sys = psprintf("\"%s\" %s%d \"%s\"",
editorName, editor_lineno_arg, lineno, fname);
else
- sys = psprintf(SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
+ sys = psprintf("\"%s\" \"%s\"",
editorName, fname);
#endif
result = system(sys);
@@ -2643,7 +2643,7 @@ do_shell(const char *command)
#ifndef WIN32
sys = psprintf("exec %s", shellName);
#else
- sys = psprintf(SYSTEMQUOTE "\"%s\"" SYSTEMQUOTE, shellName);
+ sys = psprintf("\"%s\"", shellName);
#endif
result = system(sys);
free(sys);
diff --git a/src/include/port.h b/src/include/port.h
index 06986858b60..21c8a05d0ba 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -115,37 +115,6 @@ extern BOOL AddUserToTokenDacl(HANDLE hToken);
#define DEVNULL "/dev/null"
#endif
-/*
- * Win32 needs double quotes at the beginning and end of system()
- * strings. If not, it gets confused with multiple quoted strings.
- * It also requires double-quotes around the executable name and
- * any files used for redirection. Other args can use single-quotes.
- *
- * Generated using Win32 "CMD /?":
- *
- * 1. If all of the following conditions are met, then quote characters
- * on the command line are preserved:
- *
- * - no /S switch
- * - exactly two quote characters
- * - no special characters between the two quote characters, where special
- * is one of: &<>()@^|
- * - there are one or more whitespace characters between the two quote
- * characters
- * - the string between the two quote characters is the name of an
- * executable file.
- *
- * 2. Otherwise, old behavior is to see if the first character is a quote
- * character and if so, strip the leading character and remove the last
- * quote character on the command line, preserving any text after the last
- * quote character.
- */
-#if defined(WIN32) && !defined(__CYGWIN__)
-#define SYSTEMQUOTE "\""
-#else
-#define SYSTEMQUOTE ""
-#endif
-
/* Portable delay handling */
extern void pg_usleep(long microsec);
@@ -332,12 +301,16 @@ extern FILE *pgwin32_fopen(const char *, const char *);
#define fopen(a,b) pgwin32_fopen(a,b)
#endif
-#ifndef popen
-#define popen(a,b) _popen(a,b)
-#endif
-#ifndef pclose
+/*
+ * system() and popen() replacements to enclose the command in an extra
+ * pair of quotes.
+ */
+extern int pgwin32_system(const char *command);
+extern FILE *pgwin32_popen(const char *command, const char *type);
+
+#define system(a) pgwin32_system(a)
+#define popen(a,b) pgwin32_popen(a,b)
#define pclose(a) _pclose(a)
-#endif
/* New versions of MingW have gettimeofday, old mingw and msvc don't */
#ifndef HAVE_GETTIMEOFDAY
diff --git a/src/interfaces/ecpg/test/pg_regress_ecpg.c b/src/interfaces/ecpg/test/pg_regress_ecpg.c
index cb79b61b2d5..e9bedb5c75d 100644
--- a/src/interfaces/ecpg/test/pg_regress_ecpg.c
+++ b/src/interfaces/ecpg/test/pg_regress_ecpg.c
@@ -137,7 +137,7 @@ ecpg_start_test(const char *testname,
snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "\"%s\" >\"%s\" 2>\"%s\"" SYSTEMQUOTE,
+ "\"%s\" >\"%s\" 2>\"%s\"",
inprg,
outfile_stdout,
outfile_stderr);
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 7f2d901111c..2b770d0a721 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -38,7 +38,7 @@ OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
OBJS += chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o \
thread.o
# libpgport C files that are needed if identified by configure
-OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o snprintf.o strerror.o strlcpy.o win32error.o win32setlocale.o, $(LIBOBJS))
+OBJS += $(filter crypt.o getaddrinfo.o getpeereid.o inet_aton.o open.o system.o snprintf.o strerror.o strlcpy.o win32error.o win32setlocale.o, $(LIBOBJS))
# backend/libpq
OBJS += ip.o md5.o
# utils/mb
@@ -89,7 +89,7 @@ backend_src = $(top_srcdir)/src/backend
# For some libpgport modules, this only happens if configure decides
# the module is needed (see filter hack in OBJS, above).
-chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c pgsleep.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
+chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c inet_net_ntop.c noblock.c open.c system.c pgsleep.c pgstrcasecmp.c pqsignal.c snprintf.c strerror.c strlcpy.c thread.c win32error.c win32setlocale.c: % : $(top_srcdir)/src/port/%
rm -f $@ && $(LN_S) $< .
ip.c md5.c: % : $(backend_src)/libpq/%
@@ -150,7 +150,7 @@ clean distclean: clean-lib
# Might be left over from a Win32 client-only build
rm -f pg_config_paths.h
rm -f inet_net_ntop.c noblock.c pgstrcasecmp.c pqsignal.c thread.c
- rm -f chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c open.c snprintf.c strerror.c strlcpy.c win32error.c win32setlocale.c
+ rm -f chklocale.c crypt.c getaddrinfo.c getpeereid.c inet_aton.c open.c system.c snprintf.c strerror.c strlcpy.c win32error.c win32setlocale.c
rm -f pgsleep.c
rm -f md5.c ip.c
rm -f encnames.c wchar.c
diff --git a/src/interfaces/libpq/bcc32.mak b/src/interfaces/libpq/bcc32.mak
index 8f5cd8de470..78102fafd45 100644
--- a/src/interfaces/libpq/bcc32.mak
+++ b/src/interfaces/libpq/bcc32.mak
@@ -106,6 +106,7 @@ CLEAN :
-@erase "$(INTDIR)\dirmod.obj"
-@erase "$(INTDIR)\pgsleep.obj"
-@erase "$(INTDIR)\open.obj"
+ -@erase "$(INTDIR)\system.obj"
-@erase "$(INTDIR)\win32error.obj"
-@erase "$(OUTDIR)\$(OUTFILENAME).lib"
-@erase "$(OUTDIR)\$(OUTFILENAME)dll.lib"
@@ -149,6 +150,7 @@ LIB32_OBJS= \
"$(INTDIR)\dirmod.obj" \
"$(INTDIR)\pgsleep.obj" \
"$(INTDIR)\open.obj" \
+ "$(INTDIR)\system.obj" \
"$(INTDIR)\win32error.obj" \
"$(INTDIR)\pthread-win32.obj"
@@ -295,6 +297,11 @@ LINK32_FLAGS = -Gn -L$(BCB)\lib;$(INTDIR); -x -Tpd -v
$(CPP_PROJ) /I"." ..\..\port\open.c
<<
+"$(INTDIR)\system.obj" : ..\..\port\system.c
+ $(CPP) @<<
+ $(CPP_PROJ) /I"." ..\..\port\system.c
+<<
+
"$(INTDIR)\win32error.obj" : ..\..\port\win32error.c
$(CPP) @<<
$(CPP_PROJ) /I"." ..\..\port\win32error.c
diff --git a/src/interfaces/libpq/win32.mak b/src/interfaces/libpq/win32.mak
index ee1884fe201..23e09e98100 100644
--- a/src/interfaces/libpq/win32.mak
+++ b/src/interfaces/libpq/win32.mak
@@ -113,6 +113,7 @@ CLEAN :
-@erase "$(INTDIR)\dirmod.obj"
-@erase "$(INTDIR)\pgsleep.obj"
-@erase "$(INTDIR)\open.obj"
+ -@erase "$(INTDIR)\system.obj"
-@erase "$(INTDIR)\win32error.obj"
-@erase "$(INTDIR)\win32setlocale.obj"
-@erase "$(OUTDIR)\$(OUTFILENAME).lib"
@@ -159,6 +160,7 @@ LIB32_OBJS= \
"$(INTDIR)\dirmod.obj" \
"$(INTDIR)\pgsleep.obj" \
"$(INTDIR)\open.obj" \
+ "$(INTDIR)\system.obj" \
"$(INTDIR)\win32error.obj" \
"$(INTDIR)\win32setlocale.obj" \
"$(INTDIR)\pthread-win32.obj"
@@ -335,6 +337,11 @@ LINK32_OBJS= \
$(CPP_PROJ) /I"." ..\..\port\open.c
<<
+"$(INTDIR)\system.obj" : ..\..\port\system.c
+ $(CPP) @<<
+ $(CPP_PROJ) /I"." ..\..\port\system.c
+<<
+
"$(INTDIR)\win32error.obj" : ..\..\port\win32error.c
$(CPP) @<<
$(CPP_PROJ) /I"." ..\..\port\win32error.c
diff --git a/src/port/system.c b/src/port/system.c
new file mode 100644
index 00000000000..f9c525dfbfc
--- /dev/null
+++ b/src/port/system.c
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * system.c
+ * Win32 system() and popen() replacements
+ *
+ *
+ * Win32 needs double quotes at the beginning and end of system()
+ * strings. If not, it gets confused with multiple quoted strings.
+ * It also requires double-quotes around the executable name and
+ * any files used for redirection. Other args can use single-quotes.
+ *
+ * Generated using Win32 "CMD /?":
+ *
+ * 1. If all of the following conditions are met, then quote characters
+ * on the command line are preserved:
+ *
+ * - no /S switch
+ * - exactly two quote characters
+ * - no special characters between the two quote characters, where special
+ * is one of: &<>()@^|
+ * - there are one or more whitespace characters between the two quote
+ * characters
+ * - the string between the two quote characters is the name of an
+ * executable file.
+ *
+ * 2. Otherwise, old behavior is to see if the first character is a quote
+ * character and if so, strip the leading character and remove the last
+ * quote character on the command line, preserving any text after the last
+ * quote character.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ *
+ * src/port/system.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <windows.h>
+#include <fcntl.h>
+
+#undef system
+#undef popen
+
+int
+pgwin32_system(const char *command)
+{
+ size_t cmdlen = strlen(command);
+ char *buf;
+ int save_errno;
+ int res;
+
+ /*
+ * Create a malloc'd copy of the command string, enclosed with an extra
+ * pair of quotes
+ */
+ buf = malloc(cmdlen + 2 + 1);
+ if (buf == NULL)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ buf[0] = '"';
+ memcpy(&buf[1], command, cmdlen);
+ buf[cmdlen + 1] = '"';
+ buf[cmdlen + 2] = '\0';
+
+ res = system(buf);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+
+ return res;
+}
+
+
+FILE *
+pgwin32_popen(const char *command, const char *type)
+{
+ size_t cmdlen = strlen(command);
+ char *buf;
+ int save_errno;
+ FILE *res;
+
+ /*
+ * Create a malloc'd copy of the command string, enclosed with an extra
+ * pair of quotes
+ */
+ buf = malloc(cmdlen + 2 + 1);
+ if (buf == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ buf[0] = '"';
+ memcpy(&buf[1], command, cmdlen);
+ buf[cmdlen + 1] = '"';
+ buf[cmdlen + 2] = '\0';
+
+ res = _popen(buf, type);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+
+ return res;
+}
+
+#endif
diff --git a/src/test/isolation/isolation_main.c b/src/test/isolation/isolation_main.c
index 64c41758cba..c8d431fd953 100644
--- a/src/test/isolation/isolation_main.c
+++ b/src/test/isolation/isolation_main.c
@@ -77,7 +77,7 @@ isolation_start_test(const char *testname,
"%s ", launcher);
snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
- SYSTEMQUOTE "\"%s\" \"dbname=%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+ "\"%s\" \"dbname=%s\" < \"%s\" > \"%s\" 2>&1",
isolation_exec,
dblist->str,
infile,
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 07dd8037ac3..c41cf7e7711 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -293,7 +293,7 @@ stop_postmaster(void)
fflush(stderr);
snprintf(buf, sizeof(buf),
- SYSTEMQUOTE "\"%s/pg_ctl\" stop -D \"%s/data\" -s -m fast" SYSTEMQUOTE,
+ "\"%s/pg_ctl\" stop -D \"%s/data\" -s -m fast",
bindir, temp_install);
r = system(buf);
if (r != 0)
@@ -904,7 +904,7 @@ psql_command(const char *database, const char *query,...)
/* And now we can build and execute the shell command */
snprintf(psql_cmd, sizeof(psql_cmd),
- SYSTEMQUOTE "\"%s%spsql\" -X -c \"%s\" \"%s\"" SYSTEMQUOTE,
+ "\"%s%spsql\" -X -c \"%s\" \"%s\"",
psqldir ? psqldir : "",
psqldir ? "/" : "",
query_escaped,
@@ -1033,7 +1033,7 @@ spawn_process(const char *cmdline)
exit(2);
}
- cmdline2 = psprintf("cmd /c %s", cmdline);
+ cmdline2 = psprintf("cmd /c \"%s\"", cmdline);
#ifndef __CYGWIN__
AddUserToTokenDacl(restrictedToken);
@@ -1251,7 +1251,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
/* OK, run the diff */
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
+ "diff %s \"%s\" \"%s\" > \"%s\"",
basic_diff_opts, expectfile, resultsfile, diff);
/* Is the diff file empty? */
@@ -1284,7 +1284,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
}
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
+ "diff %s \"%s\" \"%s\" > \"%s\"",
basic_diff_opts, alt_expectfile, resultsfile, diff);
if (run_diff(cmd, diff) == 0)
@@ -1312,7 +1312,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
if (platform_expectfile)
{
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "diff %s \"%s\" \"%s\" > \"%s\"" SYSTEMQUOTE,
+ "diff %s \"%s\" \"%s\" > \"%s\"",
basic_diff_opts, default_expectfile, resultsfile, diff);
if (run_diff(cmd, diff) == 0)
@@ -1336,7 +1336,7 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul
* append to the diffs summary file.
*/
snprintf(cmd, sizeof(cmd),
- SYSTEMQUOTE "diff %s \"%s\" \"%s\" >> \"%s\"" SYSTEMQUOTE,
+ "diff %s \"%s\" \"%s\" >> \"%s\"",
pretty_diff_opts, best_expect_file, resultsfile, difffilename);
run_diff(cmd, difffilename);
@@ -2121,11 +2121,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
/* "make install" */
#ifndef WIN32_ONLY_COMPILER
snprintf(buf, sizeof(buf),
- SYSTEMQUOTE "\"%s\" -C \"%s\" DESTDIR=\"%s/install\" install > \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
+ "\"%s\" -C \"%s\" DESTDIR=\"%s/install\" install > \"%s/log/install.log\" 2>&1",
makeprog, top_builddir, temp_install, outputdir);
#else
snprintf(buf, sizeof(buf),
- SYSTEMQUOTE "perl \"%s/src/tools/msvc/install.pl\" \"%s/install\" >\"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
+ "perl \"%s/src/tools/msvc/install.pl\" \"%s/install\" >\"%s/log/install.log\" 2>&1",
top_builddir, temp_install, outputdir);
#endif
if (system(buf))
@@ -2138,7 +2138,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
{
#ifndef WIN32_ONLY_COMPILER
snprintf(buf, sizeof(buf),
- SYSTEMQUOTE "\"%s\" -C \"%s/%s\" DESTDIR=\"%s/install\" install >> \"%s/log/install.log\" 2>&1" SYSTEMQUOTE,
+ "\"%s\" -C \"%s/%s\" DESTDIR=\"%s/install\" install >> \"%s/log/install.log\" 2>&1",
makeprog, top_builddir, sl->str, temp_install, outputdir);
#else
fprintf(stderr, _("\n%s: --extra-install option not supported on this platform\n"), progname);
@@ -2155,7 +2155,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
/* initdb */
header(_("initializing database system"));
snprintf(buf, sizeof(buf),
- SYSTEMQUOTE "\"%s/initdb\" -D \"%s/data\" -L \"%s\" --noclean --nosync%s%s > \"%s/log/initdb.log\" 2>&1" SYSTEMQUOTE,
+ "\"%s/initdb\" -D \"%s/data\" -L \"%s\" --noclean --nosync%s%s > \"%s/log/initdb.log\" 2>&1",
bindir, temp_install, datadir,
debug ? " --debug" : "",
nolocale ? " --no-locale" : "",
@@ -2206,7 +2206,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
* Check if there is a postmaster running already.
*/
snprintf(buf2, sizeof(buf2),
- SYSTEMQUOTE "\"%s/psql\" -X postgres <%s 2>%s" SYSTEMQUOTE,
+ "\"%s/psql\" -X postgres <%s 2>%s",
bindir, DEVNULL, DEVNULL);
for (i = 0; i < 16; i++)
@@ -2238,7 +2238,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
*/
header(_("starting postmaster"));
snprintf(buf, sizeof(buf),
- SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE,
+ "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1",
bindir, temp_install,
debug ? " -d 5" : "",
hostname ? hostname : "",
diff --git a/src/test/regress/pg_regress_main.c b/src/test/regress/pg_regress_main.c
index a4f66b8a33f..90327b06110 100644
--- a/src/test/regress/pg_regress_main.c
+++ b/src/test/regress/pg_regress_main.c
@@ -64,7 +64,7 @@ psql_start_test(const char *testname,
"%s ", launcher);
snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
- SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+ "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1",
psqldir ? psqldir : "",
psqldir ? "/" : "",
dblist->str,
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index d06d6adf6ee..1254d89c292 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -69,7 +69,7 @@ sub mkvcbuild
srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
pgcheckdir.c pg_crc.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
- qsort.c qsort_arg.c quotes.c
+ qsort.c qsort_arg.c quotes.c system.c
sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
win32env.c win32error.c win32setlocale.c);