diff --git a/configure.in b/configure.in index fc9c52f83d2c792a76945712c86883883f7e67cf..52357a6bba3e48d1956733cfa7cae9c96666d03c 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 56e912d8c3d9e775c371c8b1c9c09e06d5a1693a..d22b6d38e291da113c796833ec651ed57fbfc7fa 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 fa0a0053bab4bebfe24b1086774075ba06fcee1f..476c6be276e0efd317be6e98f30b8f42050dfb2b 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 7f013013a0653f9373b0be9fa665cd43cfc1a8a3..91e66e6ecf465766ef88558754d3989384d4aeae 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 b53fa8bd088e6480625e26418ea686694c73a6f3..83b7f6e24d872ae8e796b3636f8a210c50f793c8 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 fc87e7d76ed166af23cf83fa91991211605af409..473d6534064c69ad74cbea480de6415040369d56 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 47fe6ccc07f357c36c40a162c9eb1fc83568fd6e..208e49bbcd060d1db8a917f74d161145689b897e 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 fd64ba824f1dd4f95f25241b93489fa85dd0d91a..dabcd680fffcf7705e8b9e8c92bbe69c92d7f4f6 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 06986858b60d88d459190f1e2ca8918618da9882..21c8a05d0baf13dbcc58813a457b55b9bc87ada2 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 cb79b61b2d5c5a885581c0c5266dc633d9cc69e4..e9bedb5c75d30c73e44b4138817b9cd7630d317b 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 7f2d901111c1559e8e0e81fb2bb7f3a8a7e45fef..2b770d0a7215a61298a829191f6c9d839c5fdc13 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 8f5cd8de470d24f6f39f629c24bbcd0a6324c0f7..78102fafd45c948a93bff59100677ddd728fdf53 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 ee1884fe201125c9ba1b2d260a879596a0efb174..23e09e981006bf11127d58910a92953814ae3deb 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 0000000000000000000000000000000000000000..f9c525dfbfcaa2519e6dda5daf4514c25e9da964 --- /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 64c41758cbaddfbbd3d28e373c5f409402977e00..c8d431fd9530cab61f4ce7fc02dbdd5d2e47fe69 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 07dd8037ac3f3323a869cc8bbaa1aad37302061d..c41cf7e7711ad7ae21b6588076158492206de846 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 a4f66b8a33f0bc7ec9c1b4773e5ba8aa0a81c8ef..90327b06110d53a788f82ded66339e62640943a0 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 d06d6adf6ee4b43e40e25be38b1dc39f4e3666df..1254d89c2929ec5590736e84f19e2662803d5206 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);