| | @@ -24,11 +24,13 @@ |
| 24 | 24 | #include <time.h> |
| 25 | 25 | #include <fcntl.h> |
| 26 | 26 | #include <sys/types.h> |
| 27 | 27 | #include <sys/stat.h> |
| 28 | 28 | #include <stdlib.h> /* atexit() */ |
| 29 | | -#if !defined(_WIN32) |
| 29 | +#if defined(_WIN32) |
| 30 | +# include <windows.h> |
| 31 | +#else |
| 30 | 32 | # include <errno.h> /* errno global */ |
| 31 | 33 | #endif |
| 32 | 34 | #if INTERFACE |
| 33 | 35 | #ifdef FOSSIL_ENABLE_JSON |
| 34 | 36 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| | @@ -329,29 +331,42 @@ |
| 329 | 331 | db_close(0); |
| 330 | 332 | } |
| 331 | 333 | } |
| 332 | 334 | |
| 333 | 335 | /* |
| 334 | | -** Search g.argv for arguments "--args FILENAME". If found, then |
| 336 | +** Convert all arguments from mbcs to UTF-8. Then |
| 337 | +** search g.argv for arguments "--args FILENAME". If found, then |
| 335 | 338 | ** (1) remove the two arguments from g.argv |
| 336 | 339 | ** (2) Read the file FILENAME |
| 337 | 340 | ** (3) Use the contents of FILE to replace the two removed arguments: |
| 338 | 341 | ** (a) Ignore blank lines in the file |
| 339 | 342 | ** (b) Each non-empty line of the file is an argument, except |
| 340 | 343 | ** (c) If the line begins with "-" and contains a space, it is broken |
| 341 | 344 | ** into two arguments at the space. |
| 342 | 345 | */ |
| 343 | | -static void expand_args_option(void){ |
| 346 | +static void expand_args_option(int argc, char **argv){ |
| 344 | 347 | Blob file = empty_blob; /* Content of the file */ |
| 345 | 348 | Blob line = empty_blob; /* One line of the file */ |
| 346 | 349 | unsigned int nLine; /* Number of lines in the file*/ |
| 347 | 350 | unsigned int i, j, k; /* Loop counters */ |
| 348 | 351 | int n; /* Number of bytes in one line */ |
| 349 | 352 | char *z; /* General use string pointer */ |
| 350 | 353 | char **newArgv; /* New expanded g.argv under construction */ |
| 351 | 354 | char const * zFileName; /* input file name */ |
| 352 | 355 | FILE * zInFile; /* input FILE */ |
| 356 | + int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */ |
| 357 | +#ifdef _WIN32 |
| 358 | + wchar_t buf[MAX_PATH]; |
| 359 | +#endif |
| 360 | + |
| 361 | + g.argc = argc; |
| 362 | + g.argv = argv; |
| 363 | +#ifdef _WIN32 |
| 364 | + GetModuleFileNameW(NULL, buf, MAX_PATH); |
| 365 | + g.argv[0] = fossil_unicode_to_utf8(buf); |
| 366 | + for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]); |
| 367 | +#endif |
| 353 | 368 | for(i=1; i<g.argc-1; i++){ |
| 354 | 369 | z = g.argv[i]; |
| 355 | 370 | if( z[0]!='-' ) continue; |
| 356 | 371 | z++; |
| 357 | 372 | if( z[0]=='-' ) z++; |
| | @@ -361,11 +376,11 @@ |
| 361 | 376 | if( i>=g.argc-1 ) return; |
| 362 | 377 | |
| 363 | 378 | zFileName = g.argv[i+1]; |
| 364 | 379 | zInFile = (0==strcmp("-",zFileName)) |
| 365 | 380 | ? stdin |
| 366 | | - : fopen(zFileName,"rb"); |
| 381 | + : fossil_fopen(zFileName,"rb"); |
| 367 | 382 | if(!zInFile){ |
| 368 | 383 | fossil_panic("Cannot open -args file [%s]", zFileName); |
| 369 | 384 | }else{ |
| 370 | 385 | blob_read_from_channel(&file, zInFile, -1); |
| 371 | 386 | if(stdin != zInFile){ |
| | @@ -381,14 +396,24 @@ |
| 381 | 396 | blob_rewind(&file); |
| 382 | 397 | while( (n = blob_line(&file, &line))>0 ){ |
| 383 | 398 | if( n<=1 ) continue; |
| 384 | 399 | z = blob_buffer(&line); |
| 385 | 400 | z[n-1] = 0; |
| 401 | + if (foundBom == -1) { |
| 402 | + static const char bom[] = { 0xEF, 0xBB, 0xBF }; |
| 403 | + foundBom = memcmp(z, bom, 3)==0; |
| 404 | + if( foundBom ) { |
| 405 | + z += 3; n -= 3; |
| 406 | + } |
| 407 | + } |
| 386 | 408 | if((n>1) && ('\r'==z[n-2])){ |
| 387 | 409 | if(n==2) continue /*empty line*/; |
| 388 | 410 | z[n-2] = 0; |
| 389 | 411 | } |
| 412 | + if (!foundBom) { |
| 413 | + z = fossil_mbcs_to_utf8(z); |
| 414 | + } |
| 390 | 415 | newArgv[j++] = z; |
| 391 | 416 | if( z[0]=='-' ){ |
| 392 | 417 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 393 | 418 | if( z[k] ){ |
| 394 | 419 | z[k] = 0; |
| | @@ -409,17 +434,14 @@ |
| 409 | 434 | */ |
| 410 | 435 | int main(int argc, char **argv){ |
| 411 | 436 | const char *zCmdName = "unknown"; |
| 412 | 437 | int idx; |
| 413 | 438 | int rc; |
| 414 | | - int i; |
| 415 | 439 | |
| 416 | 440 | sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0); |
| 417 | 441 | memset(&g, 0, sizeof(g)); |
| 418 | 442 | g.now = time(0); |
| 419 | | - g.argc = argc; |
| 420 | | - g.argv = argv; |
| 421 | 443 | #ifdef FOSSIL_ENABLE_JSON |
| 422 | 444 | #if defined(NDEBUG) |
| 423 | 445 | g.json.errorDetailParanoia = 2 /* FIXME: make configurable |
| 424 | 446 | One problem we have here is that this |
| 425 | 447 | code is needed before the db is opened, |
| | @@ -429,12 +451,11 @@ |
| 429 | 451 | #endif |
| 430 | 452 | g.json.outOpt = cson_output_opt_empty; |
| 431 | 453 | g.json.outOpt.addNewline = 1; |
| 432 | 454 | g.json.outOpt.indentation = 1 /* in CGI/server mode this can be configured */; |
| 433 | 455 | #endif /* FOSSIL_ENABLE_JSON */ |
| 434 | | - expand_args_option(); |
| 435 | | - for(i=0; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]); |
| 456 | + expand_args_option(argc, argv); |
| 436 | 457 | #ifdef FOSSIL_ENABLE_TCL |
| 437 | 458 | g.tcl.argc = g.argc; |
| 438 | 459 | g.tcl.argv = g.argv; |
| 439 | 460 | g.tcl.interp = 0; |
| 440 | 461 | #endif |
| | @@ -514,15 +535,11 @@ |
| 514 | 535 | |
| 515 | 536 | /* |
| 516 | 537 | ** Return the name of the current executable. |
| 517 | 538 | */ |
| 518 | 539 | const char *fossil_nameofexe(void){ |
| 519 | | -#ifdef _WIN32 |
| 520 | | - return _pgmptr; |
| 521 | | -#else |
| 522 | 540 | return g.argv[0]; |
| 523 | | -#endif |
| 524 | 541 | } |
| 525 | 542 | |
| 526 | 543 | /* |
| 527 | 544 | ** Exit. Take care to close the database first. |
| 528 | 545 | */ |
| | @@ -1432,11 +1449,11 @@ |
| 1432 | 1449 | blob_read_from_file(&config, zFile); |
| 1433 | 1450 | while( blob_line(&config, &line) ){ |
| 1434 | 1451 | if( !blob_token(&line, &key) ) continue; |
| 1435 | 1452 | if( blob_buffer(&key)[0]=='#' ) continue; |
| 1436 | 1453 | if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){ |
| 1437 | | - g.fDebug = fopen(blob_str(&value), "a"); |
| 1454 | + g.fDebug = fossil_fopen(blob_str(&value), "a"); |
| 1438 | 1455 | blob_reset(&value); |
| 1439 | 1456 | continue; |
| 1440 | 1457 | } |
| 1441 | 1458 | if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ |
| 1442 | 1459 | cgi_setenv("HOME", blob_str(&value)); |
| 1443 | 1460 | |