255 fwrite(fixed, strlen(fixed), 1, atout); |
260 fwrite(fixed, strlen(fixed), 1, atout); |
256 fclose(atin); |
261 fclose(atin); |
257 fclose(atout); |
262 fclose(atout); |
258 free(fixed); |
263 free(fixed); |
259 free(buffer); |
264 free(buffer); |
260 files_to_delete[num_files_to_delete] = malloc(strlen(name)+1); |
265 files_to_delete[num_files_to_delete] = (char*) malloc(strlen(name)+1); |
261 strcpy(files_to_delete[num_files_to_delete], name); |
266 strcpy(files_to_delete[num_files_to_delete], name); |
262 num_files_to_delete++; |
267 num_files_to_delete++; |
263 atname = malloc(strlen(name)+2); |
268 atname = (char*) malloc(strlen(name)+2); |
264 atname[0] = '@'; |
269 atname[0] = '@'; |
265 strcpy(atname+1, name); |
270 strcpy(atname+1, name); |
266 return atname; |
271 return atname; |
267 } |
272 } |
268 |
273 |
269 int main(int argc, char **argv) |
274 // given an argument, convert it to the windows command line safe quoted version |
|
275 // using rules from: |
|
276 // http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx |
|
277 // caller is responsible for freeing both input and output. |
|
278 char * quote_arg(char const * in_arg) { |
|
279 char *quoted = NULL; |
|
280 char *current = quoted; |
|
281 int pass; |
|
282 |
|
283 if(strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) { |
|
284 return _strdup(in_arg); |
|
285 } |
|
286 |
|
287 // process the arg twice. Once to calculate the size and then to copy it. |
|
288 for(pass=1; pass<=2; pass++) { |
|
289 char const *arg = in_arg; |
|
290 |
|
291 // initial " |
|
292 if(pass == 2) { |
|
293 *current = '\"'; |
|
294 } |
|
295 current++; |
|
296 |
|
297 // process string to be quoted until NUL |
|
298 do { |
|
299 int escapes = 0; |
|
300 |
|
301 while (*arg == '\\') { |
|
302 // count escapes. |
|
303 escapes++; |
|
304 arg++; |
|
305 } |
|
306 |
|
307 if (*arg == '\0') { |
|
308 // escape the escapes before final " |
|
309 escapes *= 2; |
|
310 } else if (*arg == '"') { |
|
311 // escape the escapes and the " |
|
312 escapes = escapes * 2 + 1; |
|
313 } else { |
|
314 // escapes aren't special, just echo them. |
|
315 } |
|
316 |
|
317 // emit some escapes |
|
318 while (escapes > 0) { |
|
319 if (pass == 2) { |
|
320 *current = '\\'; |
|
321 } |
|
322 current++; |
|
323 escapes--; |
|
324 } |
|
325 |
|
326 // and the current char |
|
327 if (pass == 2) { |
|
328 *current = *arg; |
|
329 } |
|
330 current++; |
|
331 } while( *arg++ != '\0'); |
|
332 |
|
333 // allocate the buffer |
|
334 if (pass == 1) { |
|
335 size_t alloc = (size_t) (current - quoted + (ptrdiff_t) 2); |
|
336 current = quoted = (char*) calloc(alloc, sizeof(char)); |
|
337 } |
|
338 } |
|
339 |
|
340 // final " and \0 |
|
341 *(current - 1) = '"'; |
|
342 *current = '\0'; |
|
343 |
|
344 return quoted; |
|
345 } |
|
346 |
|
347 int main(int argc, char const ** argv) |
270 { |
348 { |
271 STARTUPINFO si; |
349 STARTUPINFO si; |
272 PROCESS_INFORMATION pi; |
350 PROCESS_INFORMATION pi; |
273 unsigned short rc; |
351 unsigned short rc; |
274 |
352 |
275 char *new_at_file; |
|
276 char *old_at_file; |
|
277 char *line; |
353 char *line; |
278 int i; |
354 char *current; |
|
355 int i, cmd; |
279 DWORD exitCode; |
356 DWORD exitCode; |
280 |
357 |
281 if (argc<3 || argv[1][0] != '-' || (argv[1][1] != 'c' && argv[1][1] != 'm')) { |
358 if (argc<2 || argv[1][0] != '-' || (argv[1][1] != 'c' && argv[1][1] != 'm')) { |
282 fprintf(stderr, "Usage: fixpath -c|m<path@path@...> /cygdrive/c/WINDOWS/notepad.exe /cygdrive/c/x/test.txt\n"); |
359 fprintf(stderr, "Usage: fixpath -c|m<path@path@...> /cygdrive/c/WINDOWS/notepad.exe [/cygdrive/c/x/test.txt|@/cygdrive/c/x/atfile]\n"); |
283 exit(0); |
360 exit(0); |
284 } |
361 } |
285 |
362 |
286 if (getenv("DEBUG_FIXPATH") != NULL) { |
363 if (getenv("DEBUG_FIXPATH") != NULL) { |
287 fprintf(stderr, "fixpath input line >%s<\n", strstr(GetCommandLine(), argv[1])); |
364 char const * cmdline = GetCommandLine(); |
|
365 fprintf(stderr, "fixpath input line >%s<\n", strstr( cmdline , argv[1])); |
288 } |
366 } |
289 |
367 |
290 if (argv[1][1] == 'c' && argv[1][2] == '\0') { |
368 if (argv[1][1] == 'c' && argv[1][2] == '\0') { |
291 if (getenv("DEBUG_FIXPATH") != NULL) { |
369 if (getenv("DEBUG_FIXPATH") != NULL) { |
292 fprintf(stderr, "using cygwin mode\n"); |
370 fprintf(stderr, "fixpath using cygwin mode\n"); |
293 } |
371 } |
294 replace_cygdrive = replace_cygdrive_cygwin; |
372 replace_cygdrive = replace_cygdrive_cygwin; |
295 } else if (argv[1][1] == 'm') { |
373 } else if (argv[1][1] == 'm') { |
296 if (getenv("DEBUG_FIXPATH") != NULL) { |
374 if (getenv("DEBUG_FIXPATH") != NULL) { |
297 fprintf(stderr, "using msys mode, with path list: %s\n", &argv[1][2]); |
375 fprintf(stderr, "fixpath using msys mode, with path list: %s\n", &argv[1][2]); |
298 } |
376 } |
299 setup_msys_path_list(argv[1]); |
377 setup_msys_path_list(argv[1]); |
300 replace_cygdrive = replace_cygdrive_msys; |
378 replace_cygdrive = replace_cygdrive_msys; |
301 } else { |
379 } else { |
302 fprintf(stderr, "Unknown mode: %s\n", argv[1]); |
380 fprintf(stderr, "fixpath Unknown mode: %s\n", argv[1]); |
303 exit(-1); |
381 exit(-1); |
304 } |
382 } |
305 line = replace_cygdrive(strstr(GetCommandLine(), argv[2])); |
383 |
306 |
384 i = 2; |
307 for (i=1; i<argc; ++i) { |
385 |
308 if (argv[i][0] == '@') { |
386 // handle assignments |
309 // Found at-file! Fix it! |
387 while (i < argc) { |
310 old_at_file = replace_cygdrive(argv[i]); |
388 char const * assignment = strchr(argv[i], '='); |
311 new_at_file = fix_at_file(old_at_file); |
389 if (assignment != NULL && assignment != argv[i]) { |
312 line = replace_substring(line, old_at_file, new_at_file); |
390 size_t var_len = (size_t) (assignment - argv[i] + (ptrdiff_t) 1); |
313 } |
391 char *var = (char *) calloc(var_len, sizeof(char)); |
314 } |
392 char *val = replace_cygdrive(assignment + 1); |
|
393 memmove(var, argv[i], var_len); |
|
394 var[var_len - 1] = '\0'; |
|
395 strupr(var); |
|
396 |
|
397 if (getenv("DEBUG_FIXPATH") != NULL) { |
|
398 fprintf(stderr, "fixpath setting var >%s< to >%s<\n", var, val); |
|
399 } |
|
400 |
|
401 rc = SetEnvironmentVariable(var, val); |
|
402 if(!rc) { |
|
403 // Could not set var for some reason. Try to report why. |
|
404 const int msg_len = 80 + var_len + strlen(val); |
|
405 char * msg = (char *) alloca(msg_len); |
|
406 _snprintf_s(msg, msg_len, _TRUNCATE, "Could not set environment variable [%s=%s]", var, val); |
|
407 report_error(msg); |
|
408 exit(1); |
|
409 } |
|
410 free(var); |
|
411 free(val); |
|
412 } else { |
|
413 // no more assignments; |
|
414 break; |
|
415 } |
|
416 i++; |
|
417 } |
|
418 |
|
419 // remember index of the command |
|
420 cmd = i; |
|
421 |
|
422 // handle command and it's args. |
|
423 while (i < argc) { |
|
424 char const *replaced = replace_cygdrive(argv[i]); |
|
425 if(replaced[0] == '@') { |
|
426 // Found at-file! Fix it! |
|
427 replaced = fix_at_file(replaced); |
|
428 } |
|
429 argv[i] = quote_arg(replaced); |
|
430 i++; |
|
431 } |
|
432 |
|
433 // determine the length of the line |
|
434 line = NULL; |
|
435 // args |
|
436 for(i = cmd; i < argc; i++) { |
|
437 line += (ptrdiff_t) strlen(argv[i]); |
|
438 } |
|
439 // spaces and null |
|
440 line += (ptrdiff_t) (argc - cmd + 1); |
|
441 // allocate |
|
442 line = (char*) calloc(line - (char*) NULL, sizeof(char)); |
|
443 |
|
444 // copy in args. |
|
445 current = line; |
|
446 for(i = cmd; i < argc; i++) { |
|
447 ptrdiff_t len = strlen(argv[i]); |
|
448 if (i != cmd) { |
|
449 *current++ = ' '; |
|
450 } |
|
451 memmove(current, argv[i], len); |
|
452 current += len; |
|
453 } |
|
454 *current = '\0'; |
315 |
455 |
316 if (getenv("DEBUG_FIXPATH") != NULL) { |
456 if (getenv("DEBUG_FIXPATH") != NULL) { |
317 fprintf(stderr, "fixpath converted line >%s<\n", line); |
457 fprintf(stderr, "fixpath converted line >%s<\n", line); |
|
458 } |
|
459 |
|
460 if(cmd == argc) { |
|
461 if (getenv("DEBUG_FIXPATH") != NULL) { |
|
462 fprintf(stderr, "fixpath no command provided!\n"); |
|
463 } |
|
464 exit(0); |
318 } |
465 } |
319 |
466 |
320 ZeroMemory(&si,sizeof(si)); |
467 ZeroMemory(&si,sizeof(si)); |
321 si.cb=sizeof(si); |
468 si.cb=sizeof(si); |
322 ZeroMemory(&pi,sizeof(pi)); |
469 ZeroMemory(&pi,sizeof(pi)); |
|
470 |
|
471 fflush(stderr); |
|
472 fflush(stdout); |
323 |
473 |
324 rc = CreateProcess(NULL, |
474 rc = CreateProcess(NULL, |
325 line, |
475 line, |
326 0, |
476 0, |
327 0, |
477 0, |
328 TRUE, |
478 TRUE, |
329 0, |
479 0, |
330 0, |
480 NULL, |
331 0, |
481 NULL, |
332 &si, |
482 &si, |
333 &pi); |
483 &pi); |
334 if(!rc) { |
484 if(!rc) { |
335 // Could not start process for some reason. Try to report why: |
485 // Could not start process for some reason. Try to report why: |
336 report_error(); |
486 report_error("Could not start process!"); |
337 exit(rc); |
487 exit(126); |
338 } |
488 } |
339 |
489 |
340 WaitForSingleObject(pi.hProcess,INFINITE); |
490 WaitForSingleObject(pi.hProcess,INFINITE); |
341 GetExitCodeProcess(pi.hProcess,&exitCode); |
491 GetExitCodeProcess(pi.hProcess,&exitCode); |
342 |
492 |
343 if (getenv("DEBUG_FIXPATH") != NULL) { |
493 if (getenv("DEBUG_FIXPATH") != NULL) { |
344 for (i=0; i<num_files_to_delete; ++i) { |
494 for (i=0; i<num_files_to_delete; ++i) { |
345 fprintf(stderr, "Not deleting temporary fixpath file %s\n", |
495 fprintf(stderr, "fixpath Not deleting temporary file %s\n", |
346 files_to_delete[i]); |
496 files_to_delete[i]); |
347 } |
497 } |
348 } |
498 } else { |
349 else { |
|
350 for (i=0; i<num_files_to_delete; ++i) { |
499 for (i=0; i<num_files_to_delete; ++i) { |
351 remove(files_to_delete[i]); |
500 remove(files_to_delete[i]); |
352 } |
501 } |
353 } |
502 } |
354 |
503 |
|
504 if (exitCode != 0) { |
|
505 if (getenv("DEBUG_FIXPATH") != NULL) { |
|
506 fprintf(stderr, "fixpath exit code %d\n", |
|
507 exitCode); |
|
508 } |
|
509 } |
|
510 |
355 exit(exitCode); |
511 exit(exitCode); |
356 } |
512 } |