1 /*-------------------------------------------------------------------------
2  *
3  * system.c
4  *	   Win32 system() and popen() replacements
5  *
6  *
7  *	Win32 needs double quotes at the beginning and end of system()
8  *	strings.  If not, it gets confused with multiple quoted strings.
9  *	It also requires double-quotes around the executable name and
10  *	any files used for redirection.  Filter other args through
11  *	appendShellString() to quote them.
12  *
13  *	Generated using Win32 "CMD /?":
14  *
15  *	1. If all of the following conditions are met, then quote characters
16  *	on the command line are preserved:
17  *
18  *	 - no /S switch
19  *	 - exactly two quote characters
20  *	 - no special characters between the two quote characters, where special
21  *	   is one of: &<>()@^|
22  *	 - there are one or more whitespace characters between the two quote
23  *	   characters
24  *	 - the string between the two quote characters is the name of an
25  *	   executable file.
26  *
27  *	 2. Otherwise, old behavior is to see if the first character is a quote
28  *	 character and if so, strip the leading character and remove the last
29  *	 quote character on the command line, preserving any text after the last
30  *	 quote character.
31  *
32  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
33  *
34  * src/port/system.c
35  *
36  *-------------------------------------------------------------------------
37  */
38 
39 #if defined(WIN32) && !defined(__CYGWIN__)
40 
41 #ifndef FRONTEND
42 #include "postgres.h"
43 #else
44 #include "postgres_fe.h"
45 #endif
46 
47 #include <windows.h>
48 #include <fcntl.h>
49 
50 #undef system
51 #undef popen
52 
53 int
pgwin32_system(const char * command)54 pgwin32_system(const char *command)
55 {
56 	size_t		cmdlen = strlen(command);
57 	char	   *buf;
58 	int			save_errno;
59 	int			res;
60 
61 	/*
62 	 * Create a malloc'd copy of the command string, enclosed with an extra
63 	 * pair of quotes
64 	 */
65 	buf = malloc(cmdlen + 2 + 1);
66 	if (buf == NULL)
67 	{
68 		errno = ENOMEM;
69 		return -1;
70 	}
71 	buf[0] = '"';
72 	memcpy(&buf[1], command, cmdlen);
73 	buf[cmdlen + 1] = '"';
74 	buf[cmdlen + 2] = '\0';
75 
76 	res = system(buf);
77 
78 	save_errno = errno;
79 	free(buf);
80 	errno = save_errno;
81 
82 	return res;
83 }
84 
85 
86 FILE *
pgwin32_popen(const char * command,const char * type)87 pgwin32_popen(const char *command, const char *type)
88 {
89 	size_t		cmdlen = strlen(command);
90 	char	   *buf;
91 	int			save_errno;
92 	FILE	   *res;
93 
94 	/*
95 	 * Create a malloc'd copy of the command string, enclosed with an extra
96 	 * pair of quotes
97 	 */
98 	buf = malloc(cmdlen + 2 + 1);
99 	if (buf == NULL)
100 	{
101 		errno = ENOMEM;
102 		return NULL;
103 	}
104 	buf[0] = '"';
105 	memcpy(&buf[1], command, cmdlen);
106 	buf[cmdlen + 1] = '"';
107 	buf[cmdlen + 2] = '\0';
108 
109 	res = _popen(buf, type);
110 
111 	save_errno = errno;
112 	free(buf);
113 	errno = save_errno;
114 
115 	return res;
116 }
117 
118 #endif
119