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-2021, 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 <fcntl.h>
48 
49 #undef system
50 #undef popen
51 
52 int
pgwin32_system(const char * command)53 pgwin32_system(const char *command)
54 {
55 	size_t		cmdlen = strlen(command);
56 	char	   *buf;
57 	int			save_errno;
58 	int			res;
59 
60 	/*
61 	 * Create a malloc'd copy of the command string, enclosed with an extra
62 	 * pair of quotes
63 	 */
64 	buf = malloc(cmdlen + 2 + 1);
65 	if (buf == NULL)
66 	{
67 		errno = ENOMEM;
68 		return -1;
69 	}
70 	buf[0] = '"';
71 	memcpy(&buf[1], command, cmdlen);
72 	buf[cmdlen + 1] = '"';
73 	buf[cmdlen + 2] = '\0';
74 
75 	res = system(buf);
76 
77 	save_errno = errno;
78 	free(buf);
79 	errno = save_errno;
80 
81 	return res;
82 }
83 
84 
85 FILE *
pgwin32_popen(const char * command,const char * type)86 pgwin32_popen(const char *command, const char *type)
87 {
88 	size_t		cmdlen = strlen(command);
89 	char	   *buf;
90 	int			save_errno;
91 	FILE	   *res;
92 
93 	/*
94 	 * Create a malloc'd copy of the command string, enclosed with an extra
95 	 * pair of quotes
96 	 */
97 	buf = malloc(cmdlen + 2 + 1);
98 	if (buf == NULL)
99 	{
100 		errno = ENOMEM;
101 		return NULL;
102 	}
103 	buf[0] = '"';
104 	memcpy(&buf[1], command, cmdlen);
105 	buf[cmdlen + 1] = '"';
106 	buf[cmdlen + 2] = '\0';
107 
108 	res = _popen(buf, type);
109 
110 	save_errno = errno;
111 	free(buf);
112 	errno = save_errno;
113 
114 	return res;
115 }
116 
117 #endif
118