@@ -188,16 +188,95 @@ static int strip_prefix(LPWSTR str, int *len, LPCWSTR prefix)
188188 return 0 ;
189189}
190190
191+ static void extract_first_arg (LPWSTR command_line , LPWSTR exepath , LPWSTR buf )
192+ {
193+ LPWSTR * wargv ;
194+ int wargc ;
195+
196+ wargv = CommandLineToArgvW (command_line , & wargc );
197+ if (wargc < 1 ) {
198+ fwprintf (stderr , L"Invalid command-line: '%s'\n" , command_line );
199+ exit (1 );
200+ }
201+ if (* wargv [0 ] == L'\\' ||
202+ (isalpha (* wargv [0 ]) && wargv [0 ][1 ] == L':' ))
203+ wcscpy (buf , wargv [0 ]);
204+ else {
205+ wcscpy (buf , exepath );
206+ PathAppend (buf , wargv [0 ]);
207+ }
208+ LocalFree (wargv );
209+ }
210+
211+ #define alloc_nr (x ) (((x)+16)*3/2)
212+
213+ static LPWSTR expand_variables (LPWSTR buffer , size_t alloc )
214+ {
215+ LPWSTR buf = buffer ;
216+ size_t len = wcslen (buf );
217+
218+ for (;;) {
219+ LPWSTR atat = wcsstr (buf , L"@@" ), atat2 ;
220+ WCHAR save ;
221+ int env_len , delta ;
222+
223+ if (!atat )
224+ break ;
225+
226+ atat2 = wcsstr (atat + 2 , L"@@" );
227+ if (!atat2 )
228+ break ;
229+
230+ * atat2 = L'\0' ;
231+ env_len = GetEnvironmentVariable (atat + 2 , NULL , 0 );
232+ delta = env_len - 1 - (atat2 + 2 - atat );
233+ if (len + delta >= alloc ) {
234+ LPWSTR buf2 ;
235+ alloc = alloc_nr (alloc );
236+ if (alloc <= len + delta )
237+ alloc = len + delta + 1 ;
238+ if (buf != buffer )
239+ buf2 = realloc (buf , sizeof (WCHAR ) * alloc );
240+ else {
241+ buf2 = malloc (sizeof (WCHAR ) * alloc );
242+ if (buf2 )
243+ memcpy (buf2 , buf , sizeof (WCHAR )
244+ * (len + 1 ));
245+ }
246+ if (!buf2 ) {
247+ fwprintf (stderr ,
248+ L"Substituting '%s' results in too "
249+ L"large a command-line\n" , atat + 2 );
250+ exit (1 );
251+ }
252+ atat += buf2 - buf ;
253+ atat2 += buf2 - buf ;
254+ buf = buf2 ;
255+ }
256+ if (delta )
257+ memmove (atat2 + 2 + delta , atat2 + 2 ,
258+ sizeof (WCHAR ) * (len + 1
259+ - (atat2 + 2 - buf )));
260+ len += delta ;
261+ save = atat [env_len - 1 ];
262+ GetEnvironmentVariable (atat + 2 , atat , env_len );
263+ atat [env_len - 1 ] = save ;
264+ }
265+
266+ return buf ;
267+ }
268+
191269static int configure_via_resource (LPWSTR basename , LPWSTR exepath , LPWSTR exep ,
192270 LPWSTR * prefix_args , int * prefix_args_len ,
193271 int * is_git_command , LPWSTR * working_directory , int * full_path ,
194272 int * skip_arguments , int * allocate_console , int * show_console )
195273{
196- int id , minimal_search_path , needs_a_console , no_hide , wargc ;
274+ int i , id , minimal_search_path , needs_a_console , no_hide , wargc ;
197275 LPWSTR * wargv ;
198276
199277#define BUFSIZE 65536
200278 static WCHAR buf [BUFSIZE ];
279+ LPWSTR buf2 = buf ;
201280 int len ;
202281
203282 for (id = 0 ; ; id ++ ) {
@@ -237,74 +316,59 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
237316 if (!id )
238317 SetEnvironmentVariable (L"EXEPATH" , exepath );
239318
240- for (;;) {
241- LPWSTR atat = wcsstr (buf , L"@@" ), atat2 ;
242- WCHAR save ;
243- int env_len , delta ;
244-
245- if (!atat )
246- break ;
247-
248- atat2 = wcsstr (atat + 2 , L"@@" );
249- if (!atat2 )
250- break ;
251-
252- * atat2 = L'\0' ;
253- env_len = GetEnvironmentVariable (atat + 2 , NULL , 0 );
254- delta = env_len - 1 - (atat2 + 2 - atat );
255- if (len + delta >= BUFSIZE ) {
256- fwprintf (stderr ,
257- L"Substituting '%s' results in too "
258- L"large a command-line\n" , atat + 2 );
259- exit (1 );
260- }
261- if (delta )
262- memmove (atat2 + 2 + delta , atat2 + 2 ,
263- sizeof (WCHAR ) * (len + 1
264- - (atat2 + 2 - buf )));
265- len += delta ;
266- save = atat [env_len - 1 ];
267- GetEnvironmentVariable (atat + 2 , atat , env_len );
268- atat [env_len - 1 ] = save ;
269- }
319+ buf2 = expand_variables (buf , BUFSIZE );
270320
271- /* parse first argument */
272- wargv = CommandLineToArgvW (buf , & wargc );
273- if (wargc < 1 ) {
274- fwprintf (stderr , L"Invalid command-line: '%s'\n" , buf );
275- exit (1 );
276- }
277- if (* wargv [0 ] == L'\\' ||
278- (isalpha (* wargv [0 ]) && wargv [0 ][1 ] == L':' ))
279- wcscpy (exep , wargv [0 ]);
280- else {
281- wcscpy (exep , exepath );
282- PathAppend (exep , wargv [0 ]);
283- }
284- LocalFree (wargv );
321+ extract_first_arg (buf2 , exepath , exep );
285322
286323 if (_waccess (exep , 0 ) != -1 )
287324 break ;
288325 fwprintf (stderr ,
289326 L"Skipping command-line '%s'\n('%s' not found)\n" ,
290- buf , exep );
327+ buf2 , exep );
291328 }
292329
293- * prefix_args = buf ;
294- * prefix_args_len = wcslen (buf );
330+ * prefix_args = buf2 ;
331+ * prefix_args_len = wcslen (buf2 );
295332
296333 * is_git_command = 0 ;
297- * working_directory = (LPWSTR ) 1 ;
298334 wargv = CommandLineToArgvW (GetCommandLine (), & wargc );
299- if ( wargc > 1 ) {
300- if (!wcscmp (L"--no-cd" , wargv [1 ])) {
335+ for ( i = 1 ; i < wargc ; i ++ ) {
336+ if (!wcscmp (L"--no-cd" , wargv [i ]))
301337 * working_directory = NULL ;
302- * skip_arguments = 1 ;
303- }
304- else if (!wcsncmp (L"--cd=" , wargv [1 ], 5 )) {
305- * working_directory = wcsdup (wargv [1 ] + 5 );
306- * skip_arguments = 1 ;
338+ else if (!wcscmp (L"--cd-to-home" , wargv [i ]))
339+ * working_directory = (LPWSTR ) 1 ;
340+ else if (!wcsncmp (L"--cd=" , wargv [i ], 5 ))
341+ * working_directory = wcsdup (wargv [i ] + 5 );
342+ else if (!wcscmp (L"--minimal-search-path" , wargv [i ]))
343+ minimal_search_path = 1 ;
344+ else if (!wcscmp (L"--no-minimal-search-path" , wargv [i ]))
345+ minimal_search_path = 0 ;
346+ else if (!wcscmp (L"--needs-console" , wargv [i ]))
347+ needs_a_console = 1 ;
348+ else if (!wcscmp (L"--no-needs-console" , wargv [i ]))
349+ needs_a_console = 0 ;
350+ else if (!wcscmp (L"--hide" , wargv [i ]))
351+ no_hide = 0 ;
352+ else if (!wcscmp (L"--no-hide" , wargv [i ]))
353+ no_hide = 1 ;
354+ else if (!wcsncmp (L"--command=" , wargv [i ], 10 )) {
355+ LPWSTR expanded ;
356+
357+ wargv [i ] += 10 ;
358+ expanded = expand_variables (wargv [i ], wcslen (wargv [i ]));
359+ if (expanded == wargv [i ])
360+ expanded = wcsdup (expanded );
361+
362+ extract_first_arg (expanded , exepath , exep );
363+
364+ * prefix_args = expanded ;
365+ * prefix_args_len = wcslen (* prefix_args );
366+ * skip_arguments = i ;
367+ break ;
307368 }
369+ else
370+ break ;
371+ * skip_arguments = i ;
308372 }
309373 if (minimal_search_path )
310374 * full_path = 0 ;
0 commit comments