Fossil SCM

Merge the latest trunk changes and the mingw-broken-cmdline branch into unicode-cmdline.

drh 2012-09-11 11:57 unicode-cmdline merge
Commit b19ef490fdbe5822c893ae12ea8de463575a33e1
+24 -2
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -451,10 +451,32 @@
451451
}
452452
}
453453
manifest_destroy(pFrom);
454454
manifest_destroy(pTo);
455455
}
456
+
457
+/*
458
+** Return the name of the external diff command, or return NULL if
459
+** no external diff command is defined.
460
+*/
461
+const char *diff_command_external(int guiDiff){
462
+ char *zDefault;
463
+ const char *zName;
464
+
465
+ if( guiDiff ){
466
+#if defined(_WIN32)
467
+ zDefault = "WinDiff.exe";
468
+#else
469
+ zDefault = 0;
470
+#endif
471
+ zName = "gdiff-command";
472
+ }else{
473
+ zDefault = 0;
474
+ zName = "diff-command";
475
+ }
476
+ return db_get(zName, zDefault);
477
+}
456478
457479
/*
458480
** COMMAND: diff
459481
** COMMAND: gdiff
460482
**
@@ -522,11 +544,11 @@
522544
}
523545
if( zTo==0 ){
524546
db_must_be_within_tree();
525547
verify_all_options();
526548
if( !isInternDiff ){
527
- zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
549
+ zDiffCmd = diff_command_external(isGDiff);
528550
}
529551
if( g.argc>=3 ){
530552
for(f=2; f<g.argc; ++f){
531553
diff_one_against_disk(zFrom, zDiffCmd, diffFlags, g.argv[f]);
532554
}
@@ -537,11 +559,11 @@
537559
fossil_fatal("must use --from if --to is present");
538560
}else{
539561
db_find_and_open_repository(0, 0);
540562
verify_all_options();
541563
if( !isInternDiff ){
542
- zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
564
+ zDiffCmd = diff_command_external(isGDiff);
543565
}
544566
if( g.argc>=3 ){
545567
for(f=2; f<g.argc; ++f){
546568
diff_one_two_versions(zFrom, zTo, zDiffCmd, diffFlags, g.argv[f]);
547569
}
548570
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -451,10 +451,32 @@
451 }
452 }
453 manifest_destroy(pFrom);
454 manifest_destroy(pTo);
455 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
457 /*
458 ** COMMAND: diff
459 ** COMMAND: gdiff
460 **
@@ -522,11 +544,11 @@
522 }
523 if( zTo==0 ){
524 db_must_be_within_tree();
525 verify_all_options();
526 if( !isInternDiff ){
527 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
528 }
529 if( g.argc>=3 ){
530 for(f=2; f<g.argc; ++f){
531 diff_one_against_disk(zFrom, zDiffCmd, diffFlags, g.argv[f]);
532 }
@@ -537,11 +559,11 @@
537 fossil_fatal("must use --from if --to is present");
538 }else{
539 db_find_and_open_repository(0, 0);
540 verify_all_options();
541 if( !isInternDiff ){
542 zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
543 }
544 if( g.argc>=3 ){
545 for(f=2; f<g.argc; ++f){
546 diff_one_two_versions(zFrom, zTo, zDiffCmd, diffFlags, g.argv[f]);
547 }
548
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -451,10 +451,32 @@
451 }
452 }
453 manifest_destroy(pFrom);
454 manifest_destroy(pTo);
455 }
456
457 /*
458 ** Return the name of the external diff command, or return NULL if
459 ** no external diff command is defined.
460 */
461 const char *diff_command_external(int guiDiff){
462 char *zDefault;
463 const char *zName;
464
465 if( guiDiff ){
466 #if defined(_WIN32)
467 zDefault = "WinDiff.exe";
468 #else
469 zDefault = 0;
470 #endif
471 zName = "gdiff-command";
472 }else{
473 zDefault = 0;
474 zName = "diff-command";
475 }
476 return db_get(zName, zDefault);
477 }
478
479 /*
480 ** COMMAND: diff
481 ** COMMAND: gdiff
482 **
@@ -522,11 +544,11 @@
544 }
545 if( zTo==0 ){
546 db_must_be_within_tree();
547 verify_all_options();
548 if( !isInternDiff ){
549 zDiffCmd = diff_command_external(isGDiff);
550 }
551 if( g.argc>=3 ){
552 for(f=2; f<g.argc; ++f){
553 diff_one_against_disk(zFrom, zDiffCmd, diffFlags, g.argv[f]);
554 }
@@ -537,11 +559,11 @@
559 fossil_fatal("must use --from if --to is present");
560 }else{
561 db_find_and_open_repository(0, 0);
562 verify_all_options();
563 if( !isInternDiff ){
564 zDiffCmd = diff_command_external(isGDiff);
565 }
566 if( g.argc>=3 ){
567 for(f=2; f<g.argc; ++f){
568 diff_one_two_versions(zFrom, zTo, zDiffCmd, diffFlags, g.argv[f]);
569 }
570
+125 -7
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329329
free(g.zErrMsg);
330330
if(g.db){
331331
db_close(0);
332332
}
333333
}
334
+
335
+#if defined(_WIN32)
336
+/*
337
+** Parse the command-line arguments passed to windows. We do this
338
+** ourselves to work around bugs in the command-line parsing of MinGW.
339
+** It is possible (in theory) to only use this routine when compiling
340
+** with MinGW and to use built-in command-line parsing for MSVC and
341
+** MinGW-64. However, the code is here, it is efficient, and works, and
342
+** by using it in all cases we do a better job of testing it. If you suspect
343
+** a bug in this code, test your theory by invoking "fossil test-echo".
344
+**
345
+** This routine is copied from TCL with some reformatting.
346
+** The original comment text follows:
347
+**
348
+** Parse the Windows command line string into argc/argv. Done here
349
+** because we don't trust the builtin argument parser in crt0. Windows
350
+** applications are responsible for breaking their command line into
351
+** arguments.
352
+**
353
+** 2N backslashes + quote -> N backslashes + begin quoted string
354
+** 2N + 1 backslashes + quote -> literal
355
+** N backslashes + non-quote -> literal
356
+** quote + quote in a quoted string -> single quote
357
+** quote + quote not in quoted string -> empty string
358
+** quote -> begin quoted string
359
+**
360
+** Results:
361
+** Fills argcPtr with the number of arguments and argvPtr with the array
362
+** of arguments.
363
+*/
364
+#include <tchar.h>
365
+#define tchar_isspace(X) ((X)==TEXT(' ') || (X)==TEXT('\t'))
366
+static void parse_windows_command_line(
367
+ int *argcPtr, /* Filled with number of argument strings. */
368
+ void *argvPtr /* Filled with argument strings (malloc'd). */
369
+){
370
+ TCHAR *cmdLine, *p, *arg, *argSpace;
371
+ TCHAR **argv;
372
+ int argc, size, inquote, copy, slashes;
373
+
374
+ cmdLine = GetCommandLine();
375
+
376
+ /*
377
+ ** Precompute an overly pessimistic guess at the number of arguments in
378
+ ** the command line by counting non-space spans.
379
+ */
380
+ size = 2;
381
+ for(p=cmdLine; *p!=TEXT('\0'); p++){
382
+ if( tchar_isspace(*p) ){
383
+ size++;
384
+ while( tchar_isspace(*p) ){
385
+ p++;
386
+ }
387
+ if( *p==TEXT('\0') ){
388
+ break;
389
+ }
390
+ }
391
+ }
392
+
393
+ argSpace = fossil_malloc(size * sizeof(char*)
394
+ + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
395
+ argv = (TCHAR**)argSpace;
396
+ argSpace += size*(sizeof(char*)/sizeof(TCHAR));
397
+ size--;
398
+
399
+ p = cmdLine;
400
+ for(argc=0; argc<size; argc++){
401
+ argv[argc] = arg = argSpace;
402
+ while( tchar_isspace(*p) ){
403
+ p++;
404
+ }
405
+ if (*p == TEXT('\0')) {
406
+ break;
407
+ }
408
+ inquote = 0;
409
+ slashes = 0;
410
+ while(1){
411
+ copy = 1;
412
+ while( *p==TEXT('\\') ){
413
+ slashes++;
414
+ p++;
415
+ }
416
+ if( *p==TEXT('"') ){
417
+ if( (slashes&1)==0 ){
418
+ copy = 0;
419
+ if( inquote && p[1]==TEXT('"') ){
420
+ p++;
421
+ copy = 1;
422
+ }else{
423
+ inquote = !inquote;
424
+ }
425
+ }
426
+ slashes >>= 1;
427
+ }
428
+ while( slashes ){
429
+ *arg = TEXT('\\');
430
+ arg++;
431
+ slashes--;
432
+ }
433
+ if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
434
+ break;
435
+ }
436
+ if( copy!=0 ){
437
+ *arg = *p;
438
+ arg++;
439
+ }
440
+ p++;
441
+ }
442
+ *arg = '\0';
443
+ argSpace = arg + 1;
444
+ }
445
+ argv[argc] = NULL;
446
+ *argcPtr = argc;
447
+ *((TCHAR ***)argvPtr) = argv;
448
+}
449
+#endif /* defined(_WIN32) */
450
+
334451
335452
/*
336
-** Convert all arguments to UTF-8. Then search g.argv for for arguments
337
-** "--args FILENAME". If found, then
453
+** Convert all arguments from mbcs (or unicode) to UTF-8. Then
454
+** search g.argv for arguments "--args FILENAME". If found, then
338455
** (1) remove the two arguments from g.argv
339456
** (2) Read the file FILENAME
340457
** (3) Use the contents of FILE to replace the two removed arguments:
341458
** (a) Ignore blank lines in the file
342459
** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
347464
Blob file = empty_blob; /* Content of the file */
348465
Blob line = empty_blob; /* One line of the file */
349466
unsigned int nLine; /* Number of lines in the file*/
350467
unsigned int i, j, k; /* Loop counters */
351468
int n; /* Number of bytes in one line */
352
- char *z; /* General use string pointer */
353
- char **newArgv; /* New expanded g.argv under construction */
469
+ char *z; /* General use string pointer */
470
+ char **newArgv; /* New expanded g.argv under construction */
354471
char const * zFileName; /* input file name */
355472
FILE * zInFile; /* input FILE */
356473
int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
357474
#ifdef _WIN32
358475
wchar_t buf[MAX_PATH];
@@ -359,10 +476,11 @@
359476
#endif
360477
361478
g.argc = argc;
362479
g.argv = argv;
363480
#ifdef _WIN32
481
+ parse_windows_command_line(&g.argc, &g.argv);
364482
GetModuleFileNameW(NULL, buf, MAX_PATH);
365483
g.argv[0] = fossil_unicode_to_utf8(buf);
366484
#ifdef UNICODE
367485
for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
368486
#else
@@ -404,11 +522,11 @@
404522
z[n-1] = 0;
405523
if (foundBom == -1) {
406524
static const char bom[] = { 0xEF, 0xBB, 0xBF };
407525
foundBom = memcmp(z, bom, 3)==0;
408526
if( foundBom ) {
409
- z += 3; n -= 3;
527
+ z += 3; n -= 3;
410528
}
411529
}
412530
if((n>1) && ('\r'==z[n-2])){
413531
if(n==2) continue /*empty line*/;
414532
z[n-2] = 0;
@@ -1751,11 +1869,11 @@
17511869
** See also: cgi, http, winsrv
17521870
*/
17531871
void cmd_webserver(void){
17541872
int iPort, mxPort; /* Range of TCP ports allowed */
17551873
const char *zPort; /* Value of the --port option */
1756
- char *zBrowser; /* Name of web browser program */
1874
+ const char *zBrowser; /* Name of web browser program */
17571875
char *zBrowserCmd = 0; /* Command to launch the web browser */
17581876
int isUiCmd; /* True if command is "ui", not "server' */
17591877
const char *zNotFound; /* The --notfound option or NULL */
17601878
int flags = 0; /* Server flags */
17611879
@@ -1788,11 +1906,11 @@
17881906
/* Unix implementation */
17891907
if( isUiCmd ){
17901908
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17911909
zBrowser = db_get("web-browser", 0);
17921910
if( zBrowser==0 ){
1793
- static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1911
+ static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
17941912
int i;
17951913
zBrowser = "echo";
17961914
for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
17971915
if( binaryOnPath(azBrowserProg[i]) ){
17981916
zBrowser = azBrowserProg[i];
17991917
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
335 /*
336 ** Convert all arguments to UTF-8. Then search g.argv for for arguments
337 ** "--args FILENAME". If found, then
338 ** (1) remove the two arguments from g.argv
339 ** (2) Read the file FILENAME
340 ** (3) Use the contents of FILE to replace the two removed arguments:
341 ** (a) Ignore blank lines in the file
342 ** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
347 Blob file = empty_blob; /* Content of the file */
348 Blob line = empty_blob; /* One line of the file */
349 unsigned int nLine; /* Number of lines in the file*/
350 unsigned int i, j, k; /* Loop counters */
351 int n; /* Number of bytes in one line */
352 char *z; /* General use string pointer */
353 char **newArgv; /* New expanded g.argv under construction */
354 char const * zFileName; /* input file name */
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,10 +476,11 @@
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 #ifdef UNICODE
367 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
368 #else
@@ -404,11 +522,11 @@
404 z[n-1] = 0;
405 if (foundBom == -1) {
406 static const char bom[] = { 0xEF, 0xBB, 0xBF };
407 foundBom = memcmp(z, bom, 3)==0;
408 if( foundBom ) {
409 z += 3; n -= 3;
410 }
411 }
412 if((n>1) && ('\r'==z[n-2])){
413 if(n==2) continue /*empty line*/;
414 z[n-2] = 0;
@@ -1751,11 +1869,11 @@
1751 ** See also: cgi, http, winsrv
1752 */
1753 void cmd_webserver(void){
1754 int iPort, mxPort; /* Range of TCP ports allowed */
1755 const char *zPort; /* Value of the --port option */
1756 char *zBrowser; /* Name of web browser program */
1757 char *zBrowserCmd = 0; /* Command to launch the web browser */
1758 int isUiCmd; /* True if command is "ui", not "server' */
1759 const char *zNotFound; /* The --notfound option or NULL */
1760 int flags = 0; /* Server flags */
1761
@@ -1788,11 +1906,11 @@
1788 /* Unix implementation */
1789 if( isUiCmd ){
1790 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1791 zBrowser = db_get("web-browser", 0);
1792 if( zBrowser==0 ){
1793 static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1794 int i;
1795 zBrowser = "echo";
1796 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1797 if( binaryOnPath(azBrowserProg[i]) ){
1798 zBrowser = azBrowserProg[i];
1799
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
334
335 #if defined(_WIN32)
336 /*
337 ** Parse the command-line arguments passed to windows. We do this
338 ** ourselves to work around bugs in the command-line parsing of MinGW.
339 ** It is possible (in theory) to only use this routine when compiling
340 ** with MinGW and to use built-in command-line parsing for MSVC and
341 ** MinGW-64. However, the code is here, it is efficient, and works, and
342 ** by using it in all cases we do a better job of testing it. If you suspect
343 ** a bug in this code, test your theory by invoking "fossil test-echo".
344 **
345 ** This routine is copied from TCL with some reformatting.
346 ** The original comment text follows:
347 **
348 ** Parse the Windows command line string into argc/argv. Done here
349 ** because we don't trust the builtin argument parser in crt0. Windows
350 ** applications are responsible for breaking their command line into
351 ** arguments.
352 **
353 ** 2N backslashes + quote -> N backslashes + begin quoted string
354 ** 2N + 1 backslashes + quote -> literal
355 ** N backslashes + non-quote -> literal
356 ** quote + quote in a quoted string -> single quote
357 ** quote + quote not in quoted string -> empty string
358 ** quote -> begin quoted string
359 **
360 ** Results:
361 ** Fills argcPtr with the number of arguments and argvPtr with the array
362 ** of arguments.
363 */
364 #include <tchar.h>
365 #define tchar_isspace(X) ((X)==TEXT(' ') || (X)==TEXT('\t'))
366 static void parse_windows_command_line(
367 int *argcPtr, /* Filled with number of argument strings. */
368 void *argvPtr /* Filled with argument strings (malloc'd). */
369 ){
370 TCHAR *cmdLine, *p, *arg, *argSpace;
371 TCHAR **argv;
372 int argc, size, inquote, copy, slashes;
373
374 cmdLine = GetCommandLine();
375
376 /*
377 ** Precompute an overly pessimistic guess at the number of arguments in
378 ** the command line by counting non-space spans.
379 */
380 size = 2;
381 for(p=cmdLine; *p!=TEXT('\0'); p++){
382 if( tchar_isspace(*p) ){
383 size++;
384 while( tchar_isspace(*p) ){
385 p++;
386 }
387 if( *p==TEXT('\0') ){
388 break;
389 }
390 }
391 }
392
393 argSpace = fossil_malloc(size * sizeof(char*)
394 + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
395 argv = (TCHAR**)argSpace;
396 argSpace += size*(sizeof(char*)/sizeof(TCHAR));
397 size--;
398
399 p = cmdLine;
400 for(argc=0; argc<size; argc++){
401 argv[argc] = arg = argSpace;
402 while( tchar_isspace(*p) ){
403 p++;
404 }
405 if (*p == TEXT('\0')) {
406 break;
407 }
408 inquote = 0;
409 slashes = 0;
410 while(1){
411 copy = 1;
412 while( *p==TEXT('\\') ){
413 slashes++;
414 p++;
415 }
416 if( *p==TEXT('"') ){
417 if( (slashes&1)==0 ){
418 copy = 0;
419 if( inquote && p[1]==TEXT('"') ){
420 p++;
421 copy = 1;
422 }else{
423 inquote = !inquote;
424 }
425 }
426 slashes >>= 1;
427 }
428 while( slashes ){
429 *arg = TEXT('\\');
430 arg++;
431 slashes--;
432 }
433 if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
434 break;
435 }
436 if( copy!=0 ){
437 *arg = *p;
438 arg++;
439 }
440 p++;
441 }
442 *arg = '\0';
443 argSpace = arg + 1;
444 }
445 argv[argc] = NULL;
446 *argcPtr = argc;
447 *((TCHAR ***)argvPtr) = argv;
448 }
449 #endif /* defined(_WIN32) */
450
451
452 /*
453 ** Convert all arguments from mbcs (or unicode) to UTF-8. Then
454 ** search g.argv for arguments "--args FILENAME". If found, then
455 ** (1) remove the two arguments from g.argv
456 ** (2) Read the file FILENAME
457 ** (3) Use the contents of FILE to replace the two removed arguments:
458 ** (a) Ignore blank lines in the file
459 ** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
464 Blob file = empty_blob; /* Content of the file */
465 Blob line = empty_blob; /* One line of the file */
466 unsigned int nLine; /* Number of lines in the file*/
467 unsigned int i, j, k; /* Loop counters */
468 int n; /* Number of bytes in one line */
469 char *z; /* General use string pointer */
470 char **newArgv; /* New expanded g.argv under construction */
471 char const * zFileName; /* input file name */
472 FILE * zInFile; /* input FILE */
473 int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
474 #ifdef _WIN32
475 wchar_t buf[MAX_PATH];
@@ -359,10 +476,11 @@
476 #endif
477
478 g.argc = argc;
479 g.argv = argv;
480 #ifdef _WIN32
481 parse_windows_command_line(&g.argc, &g.argv);
482 GetModuleFileNameW(NULL, buf, MAX_PATH);
483 g.argv[0] = fossil_unicode_to_utf8(buf);
484 #ifdef UNICODE
485 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
486 #else
@@ -404,11 +522,11 @@
522 z[n-1] = 0;
523 if (foundBom == -1) {
524 static const char bom[] = { 0xEF, 0xBB, 0xBF };
525 foundBom = memcmp(z, bom, 3)==0;
526 if( foundBom ) {
527 z += 3; n -= 3;
528 }
529 }
530 if((n>1) && ('\r'==z[n-2])){
531 if(n==2) continue /*empty line*/;
532 z[n-2] = 0;
@@ -1751,11 +1869,11 @@
1869 ** See also: cgi, http, winsrv
1870 */
1871 void cmd_webserver(void){
1872 int iPort, mxPort; /* Range of TCP ports allowed */
1873 const char *zPort; /* Value of the --port option */
1874 const char *zBrowser; /* Name of web browser program */
1875 char *zBrowserCmd = 0; /* Command to launch the web browser */
1876 int isUiCmd; /* True if command is "ui", not "server' */
1877 const char *zNotFound; /* The --notfound option or NULL */
1878 int flags = 0; /* Server flags */
1879
@@ -1788,11 +1906,11 @@
1906 /* Unix implementation */
1907 if( isUiCmd ){
1908 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1909 zBrowser = db_get("web-browser", 0);
1910 if( zBrowser==0 ){
1911 static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1912 int i;
1913 zBrowser = "echo";
1914 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1915 if( binaryOnPath(azBrowserProg[i]) ){
1916 zBrowser = azBrowserProg[i];
1917
+125 -7
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329329
free(g.zErrMsg);
330330
if(g.db){
331331
db_close(0);
332332
}
333333
}
334
+
335
+#if defined(_WIN32)
336
+/*
337
+** Parse the command-line arguments passed to windows. We do this
338
+** ourselves to work around bugs in the command-line parsing of MinGW.
339
+** It is possible (in theory) to only use this routine when compiling
340
+** with MinGW and to use built-in command-line parsing for MSVC and
341
+** MinGW-64. However, the code is here, it is efficient, and works, and
342
+** by using it in all cases we do a better job of testing it. If you suspect
343
+** a bug in this code, test your theory by invoking "fossil test-echo".
344
+**
345
+** This routine is copied from TCL with some reformatting.
346
+** The original comment text follows:
347
+**
348
+** Parse the Windows command line string into argc/argv. Done here
349
+** because we don't trust the builtin argument parser in crt0. Windows
350
+** applications are responsible for breaking their command line into
351
+** arguments.
352
+**
353
+** 2N backslashes + quote -> N backslashes + begin quoted string
354
+** 2N + 1 backslashes + quote -> literal
355
+** N backslashes + non-quote -> literal
356
+** quote + quote in a quoted string -> single quote
357
+** quote + quote not in quoted string -> empty string
358
+** quote -> begin quoted string
359
+**
360
+** Results:
361
+** Fills argcPtr with the number of arguments and argvPtr with the array
362
+** of arguments.
363
+*/
364
+#include <tchar.h>
365
+#define tchar_isspace(X) ((X)==TEXT(' ') || (X)==TEXT('\t'))
366
+static void parse_windows_command_line(
367
+ int *argcPtr, /* Filled with number of argument strings. */
368
+ void *argvPtr /* Filled with argument strings (malloc'd). */
369
+){
370
+ TCHAR *cmdLine, *p, *arg, *argSpace;
371
+ TCHAR **argv;
372
+ int argc, size, inquote, copy, slashes;
373
+
374
+ cmdLine = GetCommandLine();
375
+
376
+ /*
377
+ ** Precompute an overly pessimistic guess at the number of arguments in
378
+ ** the command line by counting non-space spans.
379
+ */
380
+ size = 2;
381
+ for(p=cmdLine; *p!=TEXT('\0'); p++){
382
+ if( tchar_isspace(*p) ){
383
+ size++;
384
+ while( tchar_isspace(*p) ){
385
+ p++;
386
+ }
387
+ if( *p==TEXT('\0') ){
388
+ break;
389
+ }
390
+ }
391
+ }
392
+
393
+ argSpace = fossil_malloc(size * sizeof(char*)
394
+ + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
395
+ argv = (TCHAR**)argSpace;
396
+ argSpace += size*(sizeof(char*)/sizeof(TCHAR));
397
+ size--;
398
+
399
+ p = cmdLine;
400
+ for(argc=0; argc<size; argc++){
401
+ argv[argc] = arg = argSpace;
402
+ while( tchar_isspace(*p) ){
403
+ p++;
404
+ }
405
+ if (*p == TEXT('\0')) {
406
+ break;
407
+ }
408
+ inquote = 0;
409
+ slashes = 0;
410
+ while(1){
411
+ copy = 1;
412
+ while( *p==TEXT('\\') ){
413
+ slashes++;
414
+ p++;
415
+ }
416
+ if( *p==TEXT('"') ){
417
+ if( (slashes&1)==0 ){
418
+ copy = 0;
419
+ if( inquote && p[1]==TEXT('"') ){
420
+ p++;
421
+ copy = 1;
422
+ }else{
423
+ inquote = !inquote;
424
+ }
425
+ }
426
+ slashes >>= 1;
427
+ }
428
+ while( slashes ){
429
+ *arg = TEXT('\\');
430
+ arg++;
431
+ slashes--;
432
+ }
433
+ if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
434
+ break;
435
+ }
436
+ if( copy!=0 ){
437
+ *arg = *p;
438
+ arg++;
439
+ }
440
+ p++;
441
+ }
442
+ *arg = '\0';
443
+ argSpace = arg + 1;
444
+ }
445
+ argv[argc] = NULL;
446
+ *argcPtr = argc;
447
+ *((TCHAR ***)argvPtr) = argv;
448
+}
449
+#endif /* defined(_WIN32) */
450
+
334451
335452
/*
336
-** Convert all arguments to UTF-8. Then search g.argv for for arguments
337
-** "--args FILENAME". If found, then
453
+** Convert all arguments from mbcs (or unicode) to UTF-8. Then
454
+** search g.argv for arguments "--args FILENAME". If found, then
338455
** (1) remove the two arguments from g.argv
339456
** (2) Read the file FILENAME
340457
** (3) Use the contents of FILE to replace the two removed arguments:
341458
** (a) Ignore blank lines in the file
342459
** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
347464
Blob file = empty_blob; /* Content of the file */
348465
Blob line = empty_blob; /* One line of the file */
349466
unsigned int nLine; /* Number of lines in the file*/
350467
unsigned int i, j, k; /* Loop counters */
351468
int n; /* Number of bytes in one line */
352
- char *z; /* General use string pointer */
353
- char **newArgv; /* New expanded g.argv under construction */
469
+ char *z; /* General use string pointer */
470
+ char **newArgv; /* New expanded g.argv under construction */
354471
char const * zFileName; /* input file name */
355472
FILE * zInFile; /* input FILE */
356473
int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
357474
#ifdef _WIN32
358475
wchar_t buf[MAX_PATH];
@@ -359,10 +476,11 @@
359476
#endif
360477
361478
g.argc = argc;
362479
g.argv = argv;
363480
#ifdef _WIN32
481
+ parse_windows_command_line(&g.argc, &g.argv);
364482
GetModuleFileNameW(NULL, buf, MAX_PATH);
365483
g.argv[0] = fossil_unicode_to_utf8(buf);
366484
#ifdef UNICODE
367485
for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
368486
#else
@@ -404,11 +522,11 @@
404522
z[n-1] = 0;
405523
if (foundBom == -1) {
406524
static const char bom[] = { 0xEF, 0xBB, 0xBF };
407525
foundBom = memcmp(z, bom, 3)==0;
408526
if( foundBom ) {
409
- z += 3; n -= 3;
527
+ z += 3; n -= 3;
410528
}
411529
}
412530
if((n>1) && ('\r'==z[n-2])){
413531
if(n==2) continue /*empty line*/;
414532
z[n-2] = 0;
@@ -1751,11 +1869,11 @@
17511869
** See also: cgi, http, winsrv
17521870
*/
17531871
void cmd_webserver(void){
17541872
int iPort, mxPort; /* Range of TCP ports allowed */
17551873
const char *zPort; /* Value of the --port option */
1756
- char *zBrowser; /* Name of web browser program */
1874
+ const char *zBrowser; /* Name of web browser program */
17571875
char *zBrowserCmd = 0; /* Command to launch the web browser */
17581876
int isUiCmd; /* True if command is "ui", not "server' */
17591877
const char *zNotFound; /* The --notfound option or NULL */
17601878
int flags = 0; /* Server flags */
17611879
@@ -1788,11 +1906,11 @@
17881906
/* Unix implementation */
17891907
if( isUiCmd ){
17901908
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17911909
zBrowser = db_get("web-browser", 0);
17921910
if( zBrowser==0 ){
1793
- static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1911
+ static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
17941912
int i;
17951913
zBrowser = "echo";
17961914
for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
17971915
if( binaryOnPath(azBrowserProg[i]) ){
17981916
zBrowser = azBrowserProg[i];
17991917
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
335 /*
336 ** Convert all arguments to UTF-8. Then search g.argv for for arguments
337 ** "--args FILENAME". If found, then
338 ** (1) remove the two arguments from g.argv
339 ** (2) Read the file FILENAME
340 ** (3) Use the contents of FILE to replace the two removed arguments:
341 ** (a) Ignore blank lines in the file
342 ** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
347 Blob file = empty_blob; /* Content of the file */
348 Blob line = empty_blob; /* One line of the file */
349 unsigned int nLine; /* Number of lines in the file*/
350 unsigned int i, j, k; /* Loop counters */
351 int n; /* Number of bytes in one line */
352 char *z; /* General use string pointer */
353 char **newArgv; /* New expanded g.argv under construction */
354 char const * zFileName; /* input file name */
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,10 +476,11 @@
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 #ifdef UNICODE
367 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
368 #else
@@ -404,11 +522,11 @@
404 z[n-1] = 0;
405 if (foundBom == -1) {
406 static const char bom[] = { 0xEF, 0xBB, 0xBF };
407 foundBom = memcmp(z, bom, 3)==0;
408 if( foundBom ) {
409 z += 3; n -= 3;
410 }
411 }
412 if((n>1) && ('\r'==z[n-2])){
413 if(n==2) continue /*empty line*/;
414 z[n-2] = 0;
@@ -1751,11 +1869,11 @@
1751 ** See also: cgi, http, winsrv
1752 */
1753 void cmd_webserver(void){
1754 int iPort, mxPort; /* Range of TCP ports allowed */
1755 const char *zPort; /* Value of the --port option */
1756 char *zBrowser; /* Name of web browser program */
1757 char *zBrowserCmd = 0; /* Command to launch the web browser */
1758 int isUiCmd; /* True if command is "ui", not "server' */
1759 const char *zNotFound; /* The --notfound option or NULL */
1760 int flags = 0; /* Server flags */
1761
@@ -1788,11 +1906,11 @@
1788 /* Unix implementation */
1789 if( isUiCmd ){
1790 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1791 zBrowser = db_get("web-browser", 0);
1792 if( zBrowser==0 ){
1793 static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1794 int i;
1795 zBrowser = "echo";
1796 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1797 if( binaryOnPath(azBrowserProg[i]) ){
1798 zBrowser = azBrowserProg[i];
1799
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
334
335 #if defined(_WIN32)
336 /*
337 ** Parse the command-line arguments passed to windows. We do this
338 ** ourselves to work around bugs in the command-line parsing of MinGW.
339 ** It is possible (in theory) to only use this routine when compiling
340 ** with MinGW and to use built-in command-line parsing for MSVC and
341 ** MinGW-64. However, the code is here, it is efficient, and works, and
342 ** by using it in all cases we do a better job of testing it. If you suspect
343 ** a bug in this code, test your theory by invoking "fossil test-echo".
344 **
345 ** This routine is copied from TCL with some reformatting.
346 ** The original comment text follows:
347 **
348 ** Parse the Windows command line string into argc/argv. Done here
349 ** because we don't trust the builtin argument parser in crt0. Windows
350 ** applications are responsible for breaking their command line into
351 ** arguments.
352 **
353 ** 2N backslashes + quote -> N backslashes + begin quoted string
354 ** 2N + 1 backslashes + quote -> literal
355 ** N backslashes + non-quote -> literal
356 ** quote + quote in a quoted string -> single quote
357 ** quote + quote not in quoted string -> empty string
358 ** quote -> begin quoted string
359 **
360 ** Results:
361 ** Fills argcPtr with the number of arguments and argvPtr with the array
362 ** of arguments.
363 */
364 #include <tchar.h>
365 #define tchar_isspace(X) ((X)==TEXT(' ') || (X)==TEXT('\t'))
366 static void parse_windows_command_line(
367 int *argcPtr, /* Filled with number of argument strings. */
368 void *argvPtr /* Filled with argument strings (malloc'd). */
369 ){
370 TCHAR *cmdLine, *p, *arg, *argSpace;
371 TCHAR **argv;
372 int argc, size, inquote, copy, slashes;
373
374 cmdLine = GetCommandLine();
375
376 /*
377 ** Precompute an overly pessimistic guess at the number of arguments in
378 ** the command line by counting non-space spans.
379 */
380 size = 2;
381 for(p=cmdLine; *p!=TEXT('\0'); p++){
382 if( tchar_isspace(*p) ){
383 size++;
384 while( tchar_isspace(*p) ){
385 p++;
386 }
387 if( *p==TEXT('\0') ){
388 break;
389 }
390 }
391 }
392
393 argSpace = fossil_malloc(size * sizeof(char*)
394 + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
395 argv = (TCHAR**)argSpace;
396 argSpace += size*(sizeof(char*)/sizeof(TCHAR));
397 size--;
398
399 p = cmdLine;
400 for(argc=0; argc<size; argc++){
401 argv[argc] = arg = argSpace;
402 while( tchar_isspace(*p) ){
403 p++;
404 }
405 if (*p == TEXT('\0')) {
406 break;
407 }
408 inquote = 0;
409 slashes = 0;
410 while(1){
411 copy = 1;
412 while( *p==TEXT('\\') ){
413 slashes++;
414 p++;
415 }
416 if( *p==TEXT('"') ){
417 if( (slashes&1)==0 ){
418 copy = 0;
419 if( inquote && p[1]==TEXT('"') ){
420 p++;
421 copy = 1;
422 }else{
423 inquote = !inquote;
424 }
425 }
426 slashes >>= 1;
427 }
428 while( slashes ){
429 *arg = TEXT('\\');
430 arg++;
431 slashes--;
432 }
433 if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
434 break;
435 }
436 if( copy!=0 ){
437 *arg = *p;
438 arg++;
439 }
440 p++;
441 }
442 *arg = '\0';
443 argSpace = arg + 1;
444 }
445 argv[argc] = NULL;
446 *argcPtr = argc;
447 *((TCHAR ***)argvPtr) = argv;
448 }
449 #endif /* defined(_WIN32) */
450
451
452 /*
453 ** Convert all arguments from mbcs (or unicode) to UTF-8. Then
454 ** search g.argv for arguments "--args FILENAME". If found, then
455 ** (1) remove the two arguments from g.argv
456 ** (2) Read the file FILENAME
457 ** (3) Use the contents of FILE to replace the two removed arguments:
458 ** (a) Ignore blank lines in the file
459 ** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
464 Blob file = empty_blob; /* Content of the file */
465 Blob line = empty_blob; /* One line of the file */
466 unsigned int nLine; /* Number of lines in the file*/
467 unsigned int i, j, k; /* Loop counters */
468 int n; /* Number of bytes in one line */
469 char *z; /* General use string pointer */
470 char **newArgv; /* New expanded g.argv under construction */
471 char const * zFileName; /* input file name */
472 FILE * zInFile; /* input FILE */
473 int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
474 #ifdef _WIN32
475 wchar_t buf[MAX_PATH];
@@ -359,10 +476,11 @@
476 #endif
477
478 g.argc = argc;
479 g.argv = argv;
480 #ifdef _WIN32
481 parse_windows_command_line(&g.argc, &g.argv);
482 GetModuleFileNameW(NULL, buf, MAX_PATH);
483 g.argv[0] = fossil_unicode_to_utf8(buf);
484 #ifdef UNICODE
485 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
486 #else
@@ -404,11 +522,11 @@
522 z[n-1] = 0;
523 if (foundBom == -1) {
524 static const char bom[] = { 0xEF, 0xBB, 0xBF };
525 foundBom = memcmp(z, bom, 3)==0;
526 if( foundBom ) {
527 z += 3; n -= 3;
528 }
529 }
530 if((n>1) && ('\r'==z[n-2])){
531 if(n==2) continue /*empty line*/;
532 z[n-2] = 0;
@@ -1751,11 +1869,11 @@
1869 ** See also: cgi, http, winsrv
1870 */
1871 void cmd_webserver(void){
1872 int iPort, mxPort; /* Range of TCP ports allowed */
1873 const char *zPort; /* Value of the --port option */
1874 const char *zBrowser; /* Name of web browser program */
1875 char *zBrowserCmd = 0; /* Command to launch the web browser */
1876 int isUiCmd; /* True if command is "ui", not "server' */
1877 const char *zNotFound; /* The --notfound option or NULL */
1878 int flags = 0; /* Server flags */
1879
@@ -1788,11 +1906,11 @@
1906 /* Unix implementation */
1907 if( isUiCmd ){
1908 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1909 zBrowser = db_get("web-browser", 0);
1910 if( zBrowser==0 ){
1911 static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1912 int i;
1913 zBrowser = "echo";
1914 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1915 if( binaryOnPath(azBrowserProg[i]) ){
1916 zBrowser = azBrowserProg[i];
1917
+125 -7
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329329
free(g.zErrMsg);
330330
if(g.db){
331331
db_close(0);
332332
}
333333
}
334
+
335
+#if defined(_WIN32)
336
+/*
337
+** Parse the command-line arguments passed to windows. We do this
338
+** ourselves to work around bugs in the command-line parsing of MinGW.
339
+** It is possible (in theory) to only use this routine when compiling
340
+** with MinGW and to use built-in command-line parsing for MSVC and
341
+** MinGW-64. However, the code is here, it is efficient, and works, and
342
+** by using it in all cases we do a better job of testing it. If you suspect
343
+** a bug in this code, test your theory by invoking "fossil test-echo".
344
+**
345
+** This routine is copied from TCL with some reformatting.
346
+** The original comment text follows:
347
+**
348
+** Parse the Windows command line string into argc/argv. Done here
349
+** because we don't trust the builtin argument parser in crt0. Windows
350
+** applications are responsible for breaking their command line into
351
+** arguments.
352
+**
353
+** 2N backslashes + quote -> N backslashes + begin quoted string
354
+** 2N + 1 backslashes + quote -> literal
355
+** N backslashes + non-quote -> literal
356
+** quote + quote in a quoted string -> single quote
357
+** quote + quote not in quoted string -> empty string
358
+** quote -> begin quoted string
359
+**
360
+** Results:
361
+** Fills argcPtr with the number of arguments and argvPtr with the array
362
+** of arguments.
363
+*/
364
+#include <tchar.h>
365
+#define tchar_isspace(X) ((X)==TEXT(' ') || (X)==TEXT('\t'))
366
+static void parse_windows_command_line(
367
+ int *argcPtr, /* Filled with number of argument strings. */
368
+ void *argvPtr /* Filled with argument strings (malloc'd). */
369
+){
370
+ TCHAR *cmdLine, *p, *arg, *argSpace;
371
+ TCHAR **argv;
372
+ int argc, size, inquote, copy, slashes;
373
+
374
+ cmdLine = GetCommandLine();
375
+
376
+ /*
377
+ ** Precompute an overly pessimistic guess at the number of arguments in
378
+ ** the command line by counting non-space spans.
379
+ */
380
+ size = 2;
381
+ for(p=cmdLine; *p!=TEXT('\0'); p++){
382
+ if( tchar_isspace(*p) ){
383
+ size++;
384
+ while( tchar_isspace(*p) ){
385
+ p++;
386
+ }
387
+ if( *p==TEXT('\0') ){
388
+ break;
389
+ }
390
+ }
391
+ }
392
+
393
+ argSpace = fossil_malloc(size * sizeof(char*)
394
+ + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
395
+ argv = (TCHAR**)argSpace;
396
+ argSpace += size*(sizeof(char*)/sizeof(TCHAR));
397
+ size--;
398
+
399
+ p = cmdLine;
400
+ for(argc=0; argc<size; argc++){
401
+ argv[argc] = arg = argSpace;
402
+ while( tchar_isspace(*p) ){
403
+ p++;
404
+ }
405
+ if (*p == TEXT('\0')) {
406
+ break;
407
+ }
408
+ inquote = 0;
409
+ slashes = 0;
410
+ while(1){
411
+ copy = 1;
412
+ while( *p==TEXT('\\') ){
413
+ slashes++;
414
+ p++;
415
+ }
416
+ if( *p==TEXT('"') ){
417
+ if( (slashes&1)==0 ){
418
+ copy = 0;
419
+ if( inquote && p[1]==TEXT('"') ){
420
+ p++;
421
+ copy = 1;
422
+ }else{
423
+ inquote = !inquote;
424
+ }
425
+ }
426
+ slashes >>= 1;
427
+ }
428
+ while( slashes ){
429
+ *arg = TEXT('\\');
430
+ arg++;
431
+ slashes--;
432
+ }
433
+ if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
434
+ break;
435
+ }
436
+ if( copy!=0 ){
437
+ *arg = *p;
438
+ arg++;
439
+ }
440
+ p++;
441
+ }
442
+ *arg = '\0';
443
+ argSpace = arg + 1;
444
+ }
445
+ argv[argc] = NULL;
446
+ *argcPtr = argc;
447
+ *((TCHAR ***)argvPtr) = argv;
448
+}
449
+#endif /* defined(_WIN32) */
450
+
334451
335452
/*
336
-** Convert all arguments to UTF-8. Then search g.argv for for arguments
337
-** "--args FILENAME". If found, then
453
+** Convert all arguments from mbcs (or unicode) to UTF-8. Then
454
+** search g.argv for arguments "--args FILENAME". If found, then
338455
** (1) remove the two arguments from g.argv
339456
** (2) Read the file FILENAME
340457
** (3) Use the contents of FILE to replace the two removed arguments:
341458
** (a) Ignore blank lines in the file
342459
** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
347464
Blob file = empty_blob; /* Content of the file */
348465
Blob line = empty_blob; /* One line of the file */
349466
unsigned int nLine; /* Number of lines in the file*/
350467
unsigned int i, j, k; /* Loop counters */
351468
int n; /* Number of bytes in one line */
352
- char *z; /* General use string pointer */
353
- char **newArgv; /* New expanded g.argv under construction */
469
+ char *z; /* General use string pointer */
470
+ char **newArgv; /* New expanded g.argv under construction */
354471
char const * zFileName; /* input file name */
355472
FILE * zInFile; /* input FILE */
356473
int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
357474
#ifdef _WIN32
358475
wchar_t buf[MAX_PATH];
@@ -359,10 +476,11 @@
359476
#endif
360477
361478
g.argc = argc;
362479
g.argv = argv;
363480
#ifdef _WIN32
481
+ parse_windows_command_line(&g.argc, &g.argv);
364482
GetModuleFileNameW(NULL, buf, MAX_PATH);
365483
g.argv[0] = fossil_unicode_to_utf8(buf);
366484
#ifdef UNICODE
367485
for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
368486
#else
@@ -404,11 +522,11 @@
404522
z[n-1] = 0;
405523
if (foundBom == -1) {
406524
static const char bom[] = { 0xEF, 0xBB, 0xBF };
407525
foundBom = memcmp(z, bom, 3)==0;
408526
if( foundBom ) {
409
- z += 3; n -= 3;
527
+ z += 3; n -= 3;
410528
}
411529
}
412530
if((n>1) && ('\r'==z[n-2])){
413531
if(n==2) continue /*empty line*/;
414532
z[n-2] = 0;
@@ -1751,11 +1869,11 @@
17511869
** See also: cgi, http, winsrv
17521870
*/
17531871
void cmd_webserver(void){
17541872
int iPort, mxPort; /* Range of TCP ports allowed */
17551873
const char *zPort; /* Value of the --port option */
1756
- char *zBrowser; /* Name of web browser program */
1874
+ const char *zBrowser; /* Name of web browser program */
17571875
char *zBrowserCmd = 0; /* Command to launch the web browser */
17581876
int isUiCmd; /* True if command is "ui", not "server' */
17591877
const char *zNotFound; /* The --notfound option or NULL */
17601878
int flags = 0; /* Server flags */
17611879
@@ -1788,11 +1906,11 @@
17881906
/* Unix implementation */
17891907
if( isUiCmd ){
17901908
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17911909
zBrowser = db_get("web-browser", 0);
17921910
if( zBrowser==0 ){
1793
- static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1911
+ static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
17941912
int i;
17951913
zBrowser = "echo";
17961914
for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
17971915
if( binaryOnPath(azBrowserProg[i]) ){
17981916
zBrowser = azBrowserProg[i];
17991917
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
335 /*
336 ** Convert all arguments to UTF-8. Then search g.argv for for arguments
337 ** "--args FILENAME". If found, then
338 ** (1) remove the two arguments from g.argv
339 ** (2) Read the file FILENAME
340 ** (3) Use the contents of FILE to replace the two removed arguments:
341 ** (a) Ignore blank lines in the file
342 ** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
347 Blob file = empty_blob; /* Content of the file */
348 Blob line = empty_blob; /* One line of the file */
349 unsigned int nLine; /* Number of lines in the file*/
350 unsigned int i, j, k; /* Loop counters */
351 int n; /* Number of bytes in one line */
352 char *z; /* General use string pointer */
353 char **newArgv; /* New expanded g.argv under construction */
354 char const * zFileName; /* input file name */
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,10 +476,11 @@
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 #ifdef UNICODE
367 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
368 #else
@@ -404,11 +522,11 @@
404 z[n-1] = 0;
405 if (foundBom == -1) {
406 static const char bom[] = { 0xEF, 0xBB, 0xBF };
407 foundBom = memcmp(z, bom, 3)==0;
408 if( foundBom ) {
409 z += 3; n -= 3;
410 }
411 }
412 if((n>1) && ('\r'==z[n-2])){
413 if(n==2) continue /*empty line*/;
414 z[n-2] = 0;
@@ -1751,11 +1869,11 @@
1751 ** See also: cgi, http, winsrv
1752 */
1753 void cmd_webserver(void){
1754 int iPort, mxPort; /* Range of TCP ports allowed */
1755 const char *zPort; /* Value of the --port option */
1756 char *zBrowser; /* Name of web browser program */
1757 char *zBrowserCmd = 0; /* Command to launch the web browser */
1758 int isUiCmd; /* True if command is "ui", not "server' */
1759 const char *zNotFound; /* The --notfound option or NULL */
1760 int flags = 0; /* Server flags */
1761
@@ -1788,11 +1906,11 @@
1788 /* Unix implementation */
1789 if( isUiCmd ){
1790 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1791 zBrowser = db_get("web-browser", 0);
1792 if( zBrowser==0 ){
1793 static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1794 int i;
1795 zBrowser = "echo";
1796 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1797 if( binaryOnPath(azBrowserProg[i]) ){
1798 zBrowser = azBrowserProg[i];
1799
--- src/main.c
+++ src/main.c
@@ -329,14 +329,131 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
334
335 #if defined(_WIN32)
336 /*
337 ** Parse the command-line arguments passed to windows. We do this
338 ** ourselves to work around bugs in the command-line parsing of MinGW.
339 ** It is possible (in theory) to only use this routine when compiling
340 ** with MinGW and to use built-in command-line parsing for MSVC and
341 ** MinGW-64. However, the code is here, it is efficient, and works, and
342 ** by using it in all cases we do a better job of testing it. If you suspect
343 ** a bug in this code, test your theory by invoking "fossil test-echo".
344 **
345 ** This routine is copied from TCL with some reformatting.
346 ** The original comment text follows:
347 **
348 ** Parse the Windows command line string into argc/argv. Done here
349 ** because we don't trust the builtin argument parser in crt0. Windows
350 ** applications are responsible for breaking their command line into
351 ** arguments.
352 **
353 ** 2N backslashes + quote -> N backslashes + begin quoted string
354 ** 2N + 1 backslashes + quote -> literal
355 ** N backslashes + non-quote -> literal
356 ** quote + quote in a quoted string -> single quote
357 ** quote + quote not in quoted string -> empty string
358 ** quote -> begin quoted string
359 **
360 ** Results:
361 ** Fills argcPtr with the number of arguments and argvPtr with the array
362 ** of arguments.
363 */
364 #include <tchar.h>
365 #define tchar_isspace(X) ((X)==TEXT(' ') || (X)==TEXT('\t'))
366 static void parse_windows_command_line(
367 int *argcPtr, /* Filled with number of argument strings. */
368 void *argvPtr /* Filled with argument strings (malloc'd). */
369 ){
370 TCHAR *cmdLine, *p, *arg, *argSpace;
371 TCHAR **argv;
372 int argc, size, inquote, copy, slashes;
373
374 cmdLine = GetCommandLine();
375
376 /*
377 ** Precompute an overly pessimistic guess at the number of arguments in
378 ** the command line by counting non-space spans.
379 */
380 size = 2;
381 for(p=cmdLine; *p!=TEXT('\0'); p++){
382 if( tchar_isspace(*p) ){
383 size++;
384 while( tchar_isspace(*p) ){
385 p++;
386 }
387 if( *p==TEXT('\0') ){
388 break;
389 }
390 }
391 }
392
393 argSpace = fossil_malloc(size * sizeof(char*)
394 + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
395 argv = (TCHAR**)argSpace;
396 argSpace += size*(sizeof(char*)/sizeof(TCHAR));
397 size--;
398
399 p = cmdLine;
400 for(argc=0; argc<size; argc++){
401 argv[argc] = arg = argSpace;
402 while( tchar_isspace(*p) ){
403 p++;
404 }
405 if (*p == TEXT('\0')) {
406 break;
407 }
408 inquote = 0;
409 slashes = 0;
410 while(1){
411 copy = 1;
412 while( *p==TEXT('\\') ){
413 slashes++;
414 p++;
415 }
416 if( *p==TEXT('"') ){
417 if( (slashes&1)==0 ){
418 copy = 0;
419 if( inquote && p[1]==TEXT('"') ){
420 p++;
421 copy = 1;
422 }else{
423 inquote = !inquote;
424 }
425 }
426 slashes >>= 1;
427 }
428 while( slashes ){
429 *arg = TEXT('\\');
430 arg++;
431 slashes--;
432 }
433 if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
434 break;
435 }
436 if( copy!=0 ){
437 *arg = *p;
438 arg++;
439 }
440 p++;
441 }
442 *arg = '\0';
443 argSpace = arg + 1;
444 }
445 argv[argc] = NULL;
446 *argcPtr = argc;
447 *((TCHAR ***)argvPtr) = argv;
448 }
449 #endif /* defined(_WIN32) */
450
451
452 /*
453 ** Convert all arguments from mbcs (or unicode) to UTF-8. Then
454 ** search g.argv for arguments "--args FILENAME". If found, then
455 ** (1) remove the two arguments from g.argv
456 ** (2) Read the file FILENAME
457 ** (3) Use the contents of FILE to replace the two removed arguments:
458 ** (a) Ignore blank lines in the file
459 ** (b) Each non-empty line of the file is an argument, except
@@ -347,12 +464,12 @@
464 Blob file = empty_blob; /* Content of the file */
465 Blob line = empty_blob; /* One line of the file */
466 unsigned int nLine; /* Number of lines in the file*/
467 unsigned int i, j, k; /* Loop counters */
468 int n; /* Number of bytes in one line */
469 char *z; /* General use string pointer */
470 char **newArgv; /* New expanded g.argv under construction */
471 char const * zFileName; /* input file name */
472 FILE * zInFile; /* input FILE */
473 int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */
474 #ifdef _WIN32
475 wchar_t buf[MAX_PATH];
@@ -359,10 +476,11 @@
476 #endif
477
478 g.argc = argc;
479 g.argv = argv;
480 #ifdef _WIN32
481 parse_windows_command_line(&g.argc, &g.argv);
482 GetModuleFileNameW(NULL, buf, MAX_PATH);
483 g.argv[0] = fossil_unicode_to_utf8(buf);
484 #ifdef UNICODE
485 for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
486 #else
@@ -404,11 +522,11 @@
522 z[n-1] = 0;
523 if (foundBom == -1) {
524 static const char bom[] = { 0xEF, 0xBB, 0xBF };
525 foundBom = memcmp(z, bom, 3)==0;
526 if( foundBom ) {
527 z += 3; n -= 3;
528 }
529 }
530 if((n>1) && ('\r'==z[n-2])){
531 if(n==2) continue /*empty line*/;
532 z[n-2] = 0;
@@ -1751,11 +1869,11 @@
1869 ** See also: cgi, http, winsrv
1870 */
1871 void cmd_webserver(void){
1872 int iPort, mxPort; /* Range of TCP ports allowed */
1873 const char *zPort; /* Value of the --port option */
1874 const char *zBrowser; /* Name of web browser program */
1875 char *zBrowserCmd = 0; /* Command to launch the web browser */
1876 int isUiCmd; /* True if command is "ui", not "server' */
1877 const char *zNotFound; /* The --notfound option or NULL */
1878 int flags = 0; /* Server flags */
1879
@@ -1788,11 +1906,11 @@
1906 /* Unix implementation */
1907 if( isUiCmd ){
1908 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1909 zBrowser = db_get("web-browser", 0);
1910 if( zBrowser==0 ){
1911 static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1912 int i;
1913 zBrowser = "echo";
1914 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1915 if( binaryOnPath(azBrowserProg[i]) ){
1916 zBrowser = azBrowserProg[i];
1917
--- src/main.mk
+++ src/main.mk
@@ -1088,5 +1088,12 @@
10881088
10891089
10901090
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
10911091
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
10921092
1093
+#
1094
+# The list of all the targets that do not correspond to real files. This stops
1095
+# 'make' from getting confused when someone makes an error in a rule.
1096
+#
1097
+
1098
+.PHONY: all install test clean
1099
+
10931100
--- src/main.mk
+++ src/main.mk
@@ -1088,5 +1088,12 @@
1088
1089
1090 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1091 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1092
 
 
 
 
 
 
 
1093
--- src/main.mk
+++ src/main.mk
@@ -1088,5 +1088,12 @@
1088
1089
1090 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1091 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1092
1093 #
1094 # The list of all the targets that do not correspond to real files. This stops
1095 # 'make' from getting confused when someone makes an error in a rule.
1096 #
1097
1098 .PHONY: all install test clean
1099
1100
--- src/main.mk
+++ src/main.mk
@@ -1088,5 +1088,12 @@
10881088
10891089
10901090
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
10911091
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
10921092
1093
+#
1094
+# The list of all the targets that do not correspond to real files. This stops
1095
+# 'make' from getting confused when someone makes an error in a rule.
1096
+#
1097
+
1098
+.PHONY: all install test clean
1099
+
10931100
--- src/main.mk
+++ src/main.mk
@@ -1088,5 +1088,12 @@
1088
1089
1090 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1091 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1092
 
 
 
 
 
 
 
1093
--- src/main.mk
+++ src/main.mk
@@ -1088,5 +1088,12 @@
1088
1089
1090 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1091 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
1092
1093 #
1094 # The list of all the targets that do not correspond to real files. This stops
1095 # 'make' from getting confused when someone makes an error in a rule.
1096 #
1097
1098 .PHONY: all install test clean
1099
1100
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303303
304304
set opt {}
305305
writeln {
306306
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307307
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
308
+
309
+#
310
+# The list of all the targets that do not correspond to real files. This stops
311
+# 'make' from getting confused when someone makes an error in a rule.
312
+#
313
+
314
+.PHONY: all install test clean
308315
}
309316
310317
close $output_file
311318
#
312319
# End of the main.mk output
@@ -466,10 +473,15 @@
466473
# With JSON support
467474
ifdef FOSSIL_ENABLE_JSON
468475
TCC += -DFOSSIL_ENABLE_JSON=1
469476
RCC += -DFOSSIL_ENABLE_JSON=1
470477
endif
478
+
479
+# Fix buggy MinGW command line parsing
480
+ifdef MINGW_BROKEN_MAINARGS
481
+TCC += -DMINGW_BROKEN_MAINARGS
482
+endif
471483
472484
#### We add the -static option here so that we can build a static
473485
# executable that will run in a chroot jail.
474486
#
475487
LIB = -static
476488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303
304 set opt {}
305 writeln {
306 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
 
 
 
 
 
 
 
308 }
309
310 close $output_file
311 #
312 # End of the main.mk output
@@ -466,10 +473,15 @@
466 # With JSON support
467 ifdef FOSSIL_ENABLE_JSON
468 TCC += -DFOSSIL_ENABLE_JSON=1
469 RCC += -DFOSSIL_ENABLE_JSON=1
470 endif
 
 
 
 
 
471
472 #### We add the -static option here so that we can build a static
473 # executable that will run in a chroot jail.
474 #
475 LIB = -static
476
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303
304 set opt {}
305 writeln {
306 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
308
309 #
310 # The list of all the targets that do not correspond to real files. This stops
311 # 'make' from getting confused when someone makes an error in a rule.
312 #
313
314 .PHONY: all install test clean
315 }
316
317 close $output_file
318 #
319 # End of the main.mk output
@@ -466,10 +473,15 @@
473 # With JSON support
474 ifdef FOSSIL_ENABLE_JSON
475 TCC += -DFOSSIL_ENABLE_JSON=1
476 RCC += -DFOSSIL_ENABLE_JSON=1
477 endif
478
479 # Fix buggy MinGW command line parsing
480 ifdef MINGW_BROKEN_MAINARGS
481 TCC += -DMINGW_BROKEN_MAINARGS
482 endif
483
484 #### We add the -static option here so that we can build a static
485 # executable that will run in a chroot jail.
486 #
487 LIB = -static
488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303303
304304
set opt {}
305305
writeln {
306306
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307307
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
308
+
309
+#
310
+# The list of all the targets that do not correspond to real files. This stops
311
+# 'make' from getting confused when someone makes an error in a rule.
312
+#
313
+
314
+.PHONY: all install test clean
308315
}
309316
310317
close $output_file
311318
#
312319
# End of the main.mk output
@@ -466,10 +473,15 @@
466473
# With JSON support
467474
ifdef FOSSIL_ENABLE_JSON
468475
TCC += -DFOSSIL_ENABLE_JSON=1
469476
RCC += -DFOSSIL_ENABLE_JSON=1
470477
endif
478
+
479
+# Fix buggy MinGW command line parsing
480
+ifdef MINGW_BROKEN_MAINARGS
481
+TCC += -DMINGW_BROKEN_MAINARGS
482
+endif
471483
472484
#### We add the -static option here so that we can build a static
473485
# executable that will run in a chroot jail.
474486
#
475487
LIB = -static
476488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303
304 set opt {}
305 writeln {
306 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
 
 
 
 
 
 
 
308 }
309
310 close $output_file
311 #
312 # End of the main.mk output
@@ -466,10 +473,15 @@
466 # With JSON support
467 ifdef FOSSIL_ENABLE_JSON
468 TCC += -DFOSSIL_ENABLE_JSON=1
469 RCC += -DFOSSIL_ENABLE_JSON=1
470 endif
 
 
 
 
 
471
472 #### We add the -static option here so that we can build a static
473 # executable that will run in a chroot jail.
474 #
475 LIB = -static
476
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303
304 set opt {}
305 writeln {
306 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
308
309 #
310 # The list of all the targets that do not correspond to real files. This stops
311 # 'make' from getting confused when someone makes an error in a rule.
312 #
313
314 .PHONY: all install test clean
315 }
316
317 close $output_file
318 #
319 # End of the main.mk output
@@ -466,10 +473,15 @@
473 # With JSON support
474 ifdef FOSSIL_ENABLE_JSON
475 TCC += -DFOSSIL_ENABLE_JSON=1
476 RCC += -DFOSSIL_ENABLE_JSON=1
477 endif
478
479 # Fix buggy MinGW command line parsing
480 ifdef MINGW_BROKEN_MAINARGS
481 TCC += -DMINGW_BROKEN_MAINARGS
482 endif
483
484 #### We add the -static option here so that we can build a static
485 # executable that will run in a chroot jail.
486 #
487 LIB = -static
488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303303
304304
set opt {}
305305
writeln {
306306
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307307
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
308
+
309
+#
310
+# The list of all the targets that do not correspond to real files. This stops
311
+# 'make' from getting confused when someone makes an error in a rule.
312
+#
313
+
314
+.PHONY: all install test clean
308315
}
309316
310317
close $output_file
311318
#
312319
# End of the main.mk output
@@ -466,10 +473,15 @@
466473
# With JSON support
467474
ifdef FOSSIL_ENABLE_JSON
468475
TCC += -DFOSSIL_ENABLE_JSON=1
469476
RCC += -DFOSSIL_ENABLE_JSON=1
470477
endif
478
+
479
+# Fix buggy MinGW command line parsing
480
+ifdef MINGW_BROKEN_MAINARGS
481
+TCC += -DMINGW_BROKEN_MAINARGS
482
+endif
471483
472484
#### We add the -static option here so that we can build a static
473485
# executable that will run in a chroot jail.
474486
#
475487
LIB = -static
476488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303
304 set opt {}
305 writeln {
306 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
 
 
 
 
 
 
 
308 }
309
310 close $output_file
311 #
312 # End of the main.mk output
@@ -466,10 +473,15 @@
466 # With JSON support
467 ifdef FOSSIL_ENABLE_JSON
468 TCC += -DFOSSIL_ENABLE_JSON=1
469 RCC += -DFOSSIL_ENABLE_JSON=1
470 endif
 
 
 
 
 
471
472 #### We add the -static option here so that we can build a static
473 # executable that will run in a chroot jail.
474 #
475 LIB = -static
476
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -303,10 +303,17 @@
303
304 set opt {}
305 writeln {
306 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
307 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
308
309 #
310 # The list of all the targets that do not correspond to real files. This stops
311 # 'make' from getting confused when someone makes an error in a rule.
312 #
313
314 .PHONY: all install test clean
315 }
316
317 close $output_file
318 #
319 # End of the main.mk output
@@ -466,10 +473,15 @@
473 # With JSON support
474 ifdef FOSSIL_ENABLE_JSON
475 TCC += -DFOSSIL_ENABLE_JSON=1
476 RCC += -DFOSSIL_ENABLE_JSON=1
477 endif
478
479 # Fix buggy MinGW command line parsing
480 ifdef MINGW_BROKEN_MAINARGS
481 TCC += -DMINGW_BROKEN_MAINARGS
482 endif
483
484 #### We add the -static option here so that we can build a static
485 # executable that will run in a chroot jail.
486 #
487 LIB = -static
488
+27
--- src/setup.c
+++ src/setup.c
@@ -1614,10 +1614,33 @@
16141614
@ take effect. </p>
16151615
style_footer();
16161616
db_end_transaction(0);
16171617
}
16181618
1619
+/*
1620
+** Prevent the RAW SQL feature from being used to ATTACH a different
1621
+** database and query it.
1622
+**
1623
+** Actually, the RAW SQL feature only does a single statement per request.
1624
+** So it is not possible to ATTACH and then do a separate query. This
1625
+** routine is not strictly necessary, therefore. But it does not hurt
1626
+** to be paranoid.
1627
+*/
1628
+int raw_sql_query_authorizer(
1629
+ void *pError,
1630
+ int code,
1631
+ const char *zArg1,
1632
+ const char *zArg2,
1633
+ const char *zArg3,
1634
+ const char *zArg4
1635
+){
1636
+ if( code==SQLITE_ATTACH ){
1637
+ return SQLITE_DENY;
1638
+ }
1639
+ return SQLITE_OK;
1640
+}
1641
+
16191642
16201643
/*
16211644
** WEBPAGE: admin_sql
16221645
**
16231646
** Run raw SQL commands against the database file using the web interface.
@@ -1632,10 +1655,13 @@
16321655
db_begin_transaction();
16331656
style_header("Raw SQL Commands");
16341657
@ <p><b>Caution:</b> There are no restrictions on the SQL that can be
16351658
@ run by this page. You can do serious and irrepairable damage to the
16361659
@ repository. Proceed with extreme caution.</p>
1660
+ @
1661
+ @ <p>Only a the first statement in the entry box will be run.
1662
+ @ Any subsequent statements will be silently ignored.</p>
16371663
@
16381664
@ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
16391665
if( g.configOpen ){
16401666
@ <li>config &rarr; %s(db_name("configdb"))
16411667
}
@@ -1671,10 +1697,11 @@
16711697
int nCol;
16721698
int nRow = 0;
16731699
int i;
16741700
@ <hr />
16751701
login_verify_csrf_secret();
1702
+ sqlite3_set_authorizer(g.db, raw_sql_query_authorizer, 0);
16761703
rc = sqlite3_prepare_v2(g.db, zQ, -1, &pStmt, &zTail);
16771704
if( rc!=SQLITE_OK ){
16781705
@ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
16791706
sqlite3_finalize(pStmt);
16801707
}else if( pStmt==0 ){
16811708
--- src/setup.c
+++ src/setup.c
@@ -1614,10 +1614,33 @@
1614 @ take effect. </p>
1615 style_footer();
1616 db_end_transaction(0);
1617 }
1618
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1619
1620 /*
1621 ** WEBPAGE: admin_sql
1622 **
1623 ** Run raw SQL commands against the database file using the web interface.
@@ -1632,10 +1655,13 @@
1632 db_begin_transaction();
1633 style_header("Raw SQL Commands");
1634 @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
1635 @ run by this page. You can do serious and irrepairable damage to the
1636 @ repository. Proceed with extreme caution.</p>
 
 
 
1637 @
1638 @ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
1639 if( g.configOpen ){
1640 @ <li>config &rarr; %s(db_name("configdb"))
1641 }
@@ -1671,10 +1697,11 @@
1671 int nCol;
1672 int nRow = 0;
1673 int i;
1674 @ <hr />
1675 login_verify_csrf_secret();
 
1676 rc = sqlite3_prepare_v2(g.db, zQ, -1, &pStmt, &zTail);
1677 if( rc!=SQLITE_OK ){
1678 @ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
1679 sqlite3_finalize(pStmt);
1680 }else if( pStmt==0 ){
1681
--- src/setup.c
+++ src/setup.c
@@ -1614,10 +1614,33 @@
1614 @ take effect. </p>
1615 style_footer();
1616 db_end_transaction(0);
1617 }
1618
1619 /*
1620 ** Prevent the RAW SQL feature from being used to ATTACH a different
1621 ** database and query it.
1622 **
1623 ** Actually, the RAW SQL feature only does a single statement per request.
1624 ** So it is not possible to ATTACH and then do a separate query. This
1625 ** routine is not strictly necessary, therefore. But it does not hurt
1626 ** to be paranoid.
1627 */
1628 int raw_sql_query_authorizer(
1629 void *pError,
1630 int code,
1631 const char *zArg1,
1632 const char *zArg2,
1633 const char *zArg3,
1634 const char *zArg4
1635 ){
1636 if( code==SQLITE_ATTACH ){
1637 return SQLITE_DENY;
1638 }
1639 return SQLITE_OK;
1640 }
1641
1642
1643 /*
1644 ** WEBPAGE: admin_sql
1645 **
1646 ** Run raw SQL commands against the database file using the web interface.
@@ -1632,10 +1655,13 @@
1655 db_begin_transaction();
1656 style_header("Raw SQL Commands");
1657 @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
1658 @ run by this page. You can do serious and irrepairable damage to the
1659 @ repository. Proceed with extreme caution.</p>
1660 @
1661 @ <p>Only a the first statement in the entry box will be run.
1662 @ Any subsequent statements will be silently ignored.</p>
1663 @
1664 @ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
1665 if( g.configOpen ){
1666 @ <li>config &rarr; %s(db_name("configdb"))
1667 }
@@ -1671,10 +1697,11 @@
1697 int nCol;
1698 int nRow = 0;
1699 int i;
1700 @ <hr />
1701 login_verify_csrf_secret();
1702 sqlite3_set_authorizer(g.db, raw_sql_query_authorizer, 0);
1703 rc = sqlite3_prepare_v2(g.db, zQ, -1, &pStmt, &zTail);
1704 if( rc!=SQLITE_OK ){
1705 @ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
1706 sqlite3_finalize(pStmt);
1707 }else if( pStmt==0 ){
1708
+3 -3
--- src/stash.c
+++ src/stash.c
@@ -549,20 +549,20 @@
549549
"(SELECT origname FROM stashfile WHERE stashid=%d)",
550550
stashid);
551551
undo_finish();
552552
}else
553553
if( memcmp(zCmd, "diff", nCmd)==0 ){
554
- const char *zDiffCmd = db_get("diff-command", 0);
554
+ const char *zDiffCmd = diff_command_external(0);
555555
u64 diffFlags = diff_options();
556556
if( g.argc>4 ) usage("diff STASHID");
557557
stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
558558
stash_diff(stashid, zDiffCmd, diffFlags);
559559
}else
560560
if( memcmp(zCmd, "gdiff", nCmd)==0 ){
561
- const char *zDiffCmd = db_get("gdiff-command", 0);
561
+ const char *zDiffCmd = diff_command_external(1);
562562
u64 diffFlags = diff_options();
563
- if( g.argc>4 ) usage("diff STASHID");
563
+ if( g.argc>4 ) usage("gdiff STASHID");
564564
stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
565565
stash_diff(stashid, zDiffCmd, diffFlags);
566566
}else
567567
if( memcmp(zCmd, "help", nCmd)==0 ){
568568
g.argv[1] = "help";
569569
570570
ADDED test/cmdline.test
--- src/stash.c
+++ src/stash.c
@@ -549,20 +549,20 @@
549 "(SELECT origname FROM stashfile WHERE stashid=%d)",
550 stashid);
551 undo_finish();
552 }else
553 if( memcmp(zCmd, "diff", nCmd)==0 ){
554 const char *zDiffCmd = db_get("diff-command", 0);
555 u64 diffFlags = diff_options();
556 if( g.argc>4 ) usage("diff STASHID");
557 stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
558 stash_diff(stashid, zDiffCmd, diffFlags);
559 }else
560 if( memcmp(zCmd, "gdiff", nCmd)==0 ){
561 const char *zDiffCmd = db_get("gdiff-command", 0);
562 u64 diffFlags = diff_options();
563 if( g.argc>4 ) usage("diff STASHID");
564 stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
565 stash_diff(stashid, zDiffCmd, diffFlags);
566 }else
567 if( memcmp(zCmd, "help", nCmd)==0 ){
568 g.argv[1] = "help";
569
570 DDED test/cmdline.test
--- src/stash.c
+++ src/stash.c
@@ -549,20 +549,20 @@
549 "(SELECT origname FROM stashfile WHERE stashid=%d)",
550 stashid);
551 undo_finish();
552 }else
553 if( memcmp(zCmd, "diff", nCmd)==0 ){
554 const char *zDiffCmd = diff_command_external(0);
555 u64 diffFlags = diff_options();
556 if( g.argc>4 ) usage("diff STASHID");
557 stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
558 stash_diff(stashid, zDiffCmd, diffFlags);
559 }else
560 if( memcmp(zCmd, "gdiff", nCmd)==0 ){
561 const char *zDiffCmd = diff_command_external(1);
562 u64 diffFlags = diff_options();
563 if( g.argc>4 ) usage("gdiff STASHID");
564 stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
565 stash_diff(stashid, zDiffCmd, diffFlags);
566 }else
567 if( memcmp(zCmd, "help", nCmd)==0 ){
568 g.argv[1] = "help";
569
570 DDED test/cmdline.test
--- a/test/cmdline.test
+++ b/test/cmdline.test
@@ -0,0 +1,2 @@
1
+#
2
+# Copyright
--- a/test/cmdline.test
+++ b/test/cmdline.test
@@ -0,0 +1,2 @@
 
 
--- a/test/cmdline.test
+++ b/test/cmdline.test
@@ -0,0 +1,2 @@
1 #
2 # Copyright
--- a/test/cmdline.test
+++ b/test/cmdline.test
@@ -0,0 +1,2 @@
1
+#
2
+# Copyright
--- a/test/cmdline.test
+++ b/test/cmdline.test
@@ -0,0 +1,2 @@
 
 
--- a/test/cmdline.test
+++ b/test/cmdline.test
@@ -0,0 +1,2 @@
1 #
2 # Copyright
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145145
# With JSON support
146146
ifdef FOSSIL_ENABLE_JSON
147147
TCC += -DFOSSIL_ENABLE_JSON=1
148148
RCC += -DFOSSIL_ENABLE_JSON=1
149149
endif
150
+
151
+# Fix buggy MinGW command line parsing
152
+ifdef MINGW_BROKEN_MAINARGS
153
+TCC += -DMINGW_BROKEN_MAINARGS
154
+endif
150155
151156
#### We add the -static option here so that we can build a static
152157
# executable that will run in a chroot jail.
153158
#
154159
LIB = -static
155160
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145 # With JSON support
146 ifdef FOSSIL_ENABLE_JSON
147 TCC += -DFOSSIL_ENABLE_JSON=1
148 RCC += -DFOSSIL_ENABLE_JSON=1
149 endif
 
 
 
 
 
150
151 #### We add the -static option here so that we can build a static
152 # executable that will run in a chroot jail.
153 #
154 LIB = -static
155
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145 # With JSON support
146 ifdef FOSSIL_ENABLE_JSON
147 TCC += -DFOSSIL_ENABLE_JSON=1
148 RCC += -DFOSSIL_ENABLE_JSON=1
149 endif
150
151 # Fix buggy MinGW command line parsing
152 ifdef MINGW_BROKEN_MAINARGS
153 TCC += -DMINGW_BROKEN_MAINARGS
154 endif
155
156 #### We add the -static option here so that we can build a static
157 # executable that will run in a chroot jail.
158 #
159 LIB = -static
160
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145145
# With JSON support
146146
ifdef FOSSIL_ENABLE_JSON
147147
TCC += -DFOSSIL_ENABLE_JSON=1
148148
RCC += -DFOSSIL_ENABLE_JSON=1
149149
endif
150
+
151
+# Fix buggy MinGW command line parsing
152
+ifdef MINGW_BROKEN_MAINARGS
153
+TCC += -DMINGW_BROKEN_MAINARGS
154
+endif
150155
151156
#### We add the -static option here so that we can build a static
152157
# executable that will run in a chroot jail.
153158
#
154159
LIB = -static
155160
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145 # With JSON support
146 ifdef FOSSIL_ENABLE_JSON
147 TCC += -DFOSSIL_ENABLE_JSON=1
148 RCC += -DFOSSIL_ENABLE_JSON=1
149 endif
 
 
 
 
 
150
151 #### We add the -static option here so that we can build a static
152 # executable that will run in a chroot jail.
153 #
154 LIB = -static
155
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -145,10 +145,15 @@
145 # With JSON support
146 ifdef FOSSIL_ENABLE_JSON
147 TCC += -DFOSSIL_ENABLE_JSON=1
148 RCC += -DFOSSIL_ENABLE_JSON=1
149 endif
150
151 # Fix buggy MinGW command line parsing
152 ifdef MINGW_BROKEN_MAINARGS
153 TCC += -DMINGW_BROKEN_MAINARGS
154 endif
155
156 #### We add the -static option here so that we can build a static
157 # executable that will run in a chroot jail.
158 #
159 LIB = -static
160

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button