@@ -184,16 +184,95 @@ static int strip_prefix(LPWSTR str, int *len, LPCWSTR prefix)
184184 return 0 ;
185185}
186186
187+ static void extract_first_arg (LPWSTR command_line , LPWSTR exepath , LPWSTR buf )
188+ {
189+ LPWSTR * wargv ;
190+ int wargc ;
191+
192+ wargv = CommandLineToArgvW (command_line , & wargc );
193+ if (wargc < 1 ) {
194+ fwprintf (stderr , L"Invalid command-line: '%s'\n" , command_line );
195+ exit (1 );
196+ }
197+ if (* wargv [0 ] == L'\\' ||
198+ (isalpha (* wargv [0 ]) && wargv [0 ][1 ] == L':' ))
199+ wcscpy (buf , wargv [0 ]);
200+ else {
201+ wcscpy (buf , exepath );
202+ PathAppend (buf , wargv [0 ]);
203+ }
204+ LocalFree (wargv );
205+ }
206+
207+ #define alloc_nr (x ) (((x)+16)*3/2)
208+
209+ static LPWSTR expand_variables (LPWSTR buffer , size_t alloc )
210+ {
211+ LPWSTR buf = buffer ;
212+ size_t len = wcslen (buf );
213+
214+ for (;;) {
215+ LPWSTR atat = wcsstr (buf , L"@@" ), atat2 ;
216+ WCHAR save ;
217+ int env_len , delta ;
218+
219+ if (!atat )
220+ break ;
221+
222+ atat2 = wcsstr (atat + 2 , L"@@" );
223+ if (!atat2 )
224+ break ;
225+
226+ * atat2 = L'\0' ;
227+ env_len = GetEnvironmentVariable (atat + 2 , NULL , 0 );
228+ delta = env_len - 1 - (atat2 + 2 - atat );
229+ if (len + delta >= alloc ) {
230+ LPWSTR buf2 ;
231+ alloc = alloc_nr (alloc );
232+ if (alloc <= len + delta )
233+ alloc = len + delta + 1 ;
234+ if (buf != buffer )
235+ buf2 = realloc (buf , sizeof (WCHAR ) * alloc );
236+ else {
237+ buf2 = malloc (sizeof (WCHAR ) * alloc );
238+ if (buf2 )
239+ memcpy (buf2 , buf , sizeof (WCHAR )
240+ * (len + 1 ));
241+ }
242+ if (!buf2 ) {
243+ fwprintf (stderr ,
244+ L"Substituting '%s' results in too "
245+ L"large a command-line\n" , atat + 2 );
246+ exit (1 );
247+ }
248+ atat += buf2 - buf ;
249+ atat2 += buf2 - buf ;
250+ buf = buf2 ;
251+ }
252+ if (delta )
253+ memmove (atat2 + 2 + delta , atat2 + 2 ,
254+ sizeof (WCHAR ) * (len + 1
255+ - (atat2 + 2 - buf )));
256+ len += delta ;
257+ save = atat [env_len - 1 ];
258+ GetEnvironmentVariable (atat + 2 , atat , env_len );
259+ atat [env_len - 1 ] = save ;
260+ }
261+
262+ return buf ;
263+ }
264+
187265static int configure_via_resource (LPWSTR basename , LPWSTR exepath , LPWSTR exep ,
188266 LPWSTR * prefix_args , int * prefix_args_len ,
189267 int * is_git_command , LPWSTR * working_directory , int * full_path ,
190268 int * skip_arguments , int * allocate_console , int * show_console )
191269{
192- int id , minimal_search_path , needs_a_console , no_hide , wargc ;
270+ int i , id , minimal_search_path , needs_a_console , no_hide , wargc ;
193271 LPWSTR * wargv ;
194272
195273#define BUFSIZE 65536
196274 static WCHAR buf [BUFSIZE ];
275+ LPWSTR buf2 = buf ;
197276 int len ;
198277
199278 for (id = 0 ; ; id ++ ) {
@@ -233,74 +312,58 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
233312 if (!id )
234313 SetEnvironmentVariable (L"EXEPATH" , exepath );
235314
236- for (;;) {
237- LPWSTR atat = wcsstr (buf , L"@@" ), atat2 ;
238- WCHAR save ;
239- int env_len , delta ;
240-
241- if (!atat )
242- break ;
243-
244- atat2 = wcsstr (atat + 2 , L"@@" );
245- if (!atat2 )
246- break ;
247-
248- * atat2 = L'\0' ;
249- env_len = GetEnvironmentVariable (atat + 2 , NULL , 0 );
250- delta = env_len - 1 - (atat2 + 2 - atat );
251- if (len + delta >= BUFSIZE ) {
252- fwprintf (stderr ,
253- L"Substituting '%s' results in too "
254- L"large a command-line\n" , atat + 2 );
255- exit (1 );
256- }
257- if (delta )
258- memmove (atat2 + 2 + delta , atat2 + 2 ,
259- sizeof (WCHAR ) * (len + 1
260- - (atat2 + 2 - buf )));
261- len += delta ;
262- save = atat [env_len - 1 ];
263- GetEnvironmentVariable (atat + 2 , atat , env_len );
264- atat [env_len - 1 ] = save ;
265- }
315+ buf2 = expand_variables (buf , BUFSIZE );
266316
267- /* parse first argument */
268- wargv = CommandLineToArgvW (buf , & wargc );
269- if (wargc < 1 ) {
270- fwprintf (stderr , L"Invalid command-line: '%s'\n" , buf );
271- exit (1 );
272- }
273- if (* wargv [0 ] == L'\\' ||
274- (isalpha (* wargv [0 ]) && wargv [0 ][1 ] == L':' ))
275- wcscpy (exep , wargv [0 ]);
276- else {
277- wcscpy (exep , exepath );
278- PathAppend (exep , wargv [0 ]);
279- }
280- LocalFree (wargv );
317+ extract_first_arg (buf2 , exepath , exep );
281318
282319 if (_waccess (exep , 0 ) != -1 )
283320 break ;
284321 fwprintf (stderr ,
285322 L"Skipping command-line '%s'\n('%s' not found)\n" ,
286- buf , exep );
323+ buf2 , exep );
287324 }
288325
289- * prefix_args = buf ;
290- * prefix_args_len = wcslen (buf );
326+ * prefix_args = buf2 ;
327+ * prefix_args_len = wcslen (buf2 );
291328
292329 * is_git_command = 0 ;
293330 * working_directory = (LPWSTR ) 1 ;
294331 wargv = CommandLineToArgvW (GetCommandLine (), & wargc );
295- if ( wargc > 1 ) {
296- if (!wcscmp (L"--no-cd" , wargv [1 ])) {
332+ for ( i = 1 ; i < wargc ; i ++ ) {
333+ if (!wcscmp (L"--no-cd" , wargv [i ]))
297334 * working_directory = NULL ;
298- * skip_arguments = 1 ;
299- }
300- else if (!wcsncmp (L"--cd=" , wargv [1 ], 5 )) {
301- * working_directory = wcsdup (wargv [1 ] + 5 );
302- * skip_arguments = 1 ;
335+ else if (!wcsncmp (L"--cd=" , wargv [i ], 5 ))
336+ * working_directory = wcsdup (wargv [i ] + 5 );
337+ else if (!wcscmp (L"--minimal-search-path" , wargv [i ]))
338+ minimal_search_path = 1 ;
339+ else if (!wcscmp (L"--no-minimal-search-path" , wargv [i ]))
340+ minimal_search_path = 0 ;
341+ else if (!wcscmp (L"--needs-console" , wargv [i ]))
342+ needs_a_console = 1 ;
343+ else if (!wcscmp (L"--no-needs-console" , wargv [i ]))
344+ needs_a_console = 0 ;
345+ else if (!wcscmp (L"--hide" , wargv [i ]))
346+ no_hide = 0 ;
347+ else if (!wcscmp (L"--no-hide" , wargv [i ]))
348+ no_hide = 1 ;
349+ else if (!wcsncmp (L"--command=" , wargv [i ], 10 )) {
350+ LPWSTR expanded ;
351+
352+ wargv [i ] += 10 ;
353+ expanded = expand_variables (wargv [i ], wcslen (wargv [i ]));
354+ if (expanded == wargv [i ])
355+ expanded = wcsdup (expanded );
356+
357+ extract_first_arg (expanded , exepath , exep );
358+
359+ * prefix_args = expanded ;
360+ * prefix_args_len = wcslen (* prefix_args );
361+ * skip_arguments = i ;
362+ break ;
303363 }
364+ else
365+ break ;
366+ * skip_arguments = i ;
304367 }
305368 if (minimal_search_path )
306369 * full_path = 0 ;
0 commit comments