FreeRDP
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 
89 LPSTR* 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 = ((pEnd - pBeg) - 1);
161  length = (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 = (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 && *(++p))
248  p += strcspn(p, " \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 
274 LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs)
275 {
276  return NULL;
277 }
278 
279 #endif