FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
argv.c
1
20#include <winpr/config.h>
21
22#include <winpr/crt.h>
23#include <winpr/handle.h>
24
25#include <winpr/thread.h>
26
27#ifdef WINPR_HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30
31#include "../log.h"
32#define TAG WINPR_TAG("thread")
33
89LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
90{
91 const char* p = NULL;
92 size_t length = 0;
93 const char* pBeg = NULL;
94 const char* pEnd = NULL;
95 char* buffer = NULL;
96 char* pOutput = NULL;
97 int numArgs = 0;
98 LPSTR* pArgs = NULL;
99 size_t maxNumArgs = 0;
100 size_t maxBufferSize = 0;
101 size_t cmdLineLength = 0;
102 BOOL* lpEscapedChars = NULL;
103 LPSTR lpEscapedCmdLine = NULL;
104
105 if (!lpCmdLine)
106 return NULL;
107
108 if (!pNumArgs)
109 return NULL;
110
111 pArgs = NULL;
112 lpEscapedCmdLine = NULL;
113 cmdLineLength = strlen(lpCmdLine);
114 lpEscapedChars = (BOOL*)calloc(cmdLineLength + 1, sizeof(BOOL));
115
116 if (!lpEscapedChars)
117 return NULL;
118
119 if (strstr(lpCmdLine, "\\\""))
120 {
121 size_t n = 0;
122 const char* pLastEnd = NULL;
123 lpEscapedCmdLine = (char*)calloc(cmdLineLength + 1, sizeof(char));
124
125 if (!lpEscapedCmdLine)
126 {
127 free(lpEscapedChars);
128 return NULL;
129 }
130
131 p = (const char*)lpCmdLine;
132 pLastEnd = (const char*)lpCmdLine;
133 pOutput = (char*)lpEscapedCmdLine;
134
135 while (p < &lpCmdLine[cmdLineLength])
136 {
137 pBeg = strstr(p, "\\\"");
138
139 if (!pBeg)
140 {
141 length = strlen(p);
142 CopyMemory(pOutput, p, length);
143 pOutput += length;
144 break;
145 }
146
147 pEnd = pBeg + 2;
148
149 while (pBeg >= lpCmdLine)
150 {
151 if (*pBeg != '\\')
152 {
153 pBeg++;
154 break;
155 }
156
157 pBeg--;
158 }
159
160 n = WINPR_ASSERTING_INT_CAST(size_t, ((pEnd - pBeg) - 1));
161 length = WINPR_ASSERTING_INT_CAST(size_t, (pBeg - pLastEnd));
162 CopyMemory(pOutput, p, length);
163 pOutput += length;
164 p += length;
165
166 for (size_t i = 0; i < (n / 2); i++)
167 *pOutput++ = '\\';
168
169 p += n + 1;
170
171 if ((n % 2) != 0)
172 lpEscapedChars[pOutput - lpEscapedCmdLine] = TRUE;
173
174 *pOutput++ = '"';
175 pLastEnd = p;
176 }
177
178 *pOutput++ = '\0';
179 lpCmdLine = (LPCSTR)lpEscapedCmdLine;
180 cmdLineLength = strlen(lpCmdLine);
181 }
182
183 maxNumArgs = 2;
184 p = (const char*)lpCmdLine;
185
186 while (p < lpCmdLine + cmdLineLength)
187 {
188 p += strcspn(p, " \t");
189 p += strspn(p, " \t");
190 maxNumArgs++;
191 }
192
193 maxBufferSize = (maxNumArgs * (sizeof(char*))) + (cmdLineLength + 1);
194 buffer = calloc(maxBufferSize, sizeof(char));
195
196 if (!buffer)
197 {
198 free(lpEscapedCmdLine);
199 free(lpEscapedChars);
200 return NULL;
201 }
202
203 pArgs = (LPSTR*)buffer;
204 pOutput = &buffer[maxNumArgs * (sizeof(char*))];
205 p = (const char*)lpCmdLine;
206
207 while (p < lpCmdLine + cmdLineLength)
208 {
209 pBeg = p;
210
211 while (1)
212 {
213 p += strcspn(p, " \t\"\0");
214
215 if ((*p != '"') || !lpEscapedChars[p - lpCmdLine])
216 break;
217
218 p++;
219 }
220
221 if (*p != '"')
222 {
223 /* no whitespace escaped with double quotes */
224 length = WINPR_ASSERTING_INT_CAST(size_t, (p - pBeg));
225 CopyMemory(pOutput, pBeg, length);
226 pOutput[length] = '\0';
227 pArgs[numArgs++] = pOutput;
228 pOutput += (length + 1);
229 }
230 else
231 {
232 p++;
233
234 while (1)
235 {
236 p += strcspn(p, "\"\0");
237
238 if ((*p != '"') || !lpEscapedChars[p - lpCmdLine])
239 break;
240
241 p++;
242 }
243
244 if (*p != '"')
245 WLog_ERR(TAG, "parsing error: uneven number of unescaped double quotes!");
246
247 if (p[0] && p[1])
248 p += 1 + strcspn(&p[1], " \t\0");
249
250 pArgs[numArgs++] = pOutput;
251
252 while (pBeg < p)
253 {
254 if (*pBeg != '"')
255 *pOutput++ = *pBeg;
256
257 pBeg++;
258 }
259
260 *pOutput++ = '\0';
261 }
262
263 p += strspn(p, " \t");
264 }
265
266 free(lpEscapedCmdLine);
267 free(lpEscapedChars);
268 *pNumArgs = numArgs;
269 return pArgs;
270}
271
272#ifndef _WIN32
273
274LPWSTR* CommandLineToArgvW(WINPR_ATTR_UNUSED LPCWSTR lpCmdLine, WINPR_ATTR_UNUSED int* pNumArgs)
275{
276 WLog_ERR("TODO", "TODO: Implement");
277 return NULL;
278}
279
280#endif