Fossil SCM

Merge the unicode-cmdline branch into trunk.

drh 2012-09-11 12:16 trunk merge
Commit f668ff44c04174dd04bae5f594aa1fd7852f67af
+13 -19
--- src/blob.c
+++ src/blob.c
@@ -130,11 +130,11 @@
130130
}
131131
132132
/*
133133
** A reallocation function that assumes that aData came from malloc().
134134
** This function attempts to resize the buffer of the blob to hold
135
-** newSize bytes.
135
+** newSize bytes.
136136
**
137137
** No attempt is made to recover from an out-of-memory error.
138138
** If an OOM error occurs, an error message is printed on stderr
139139
** and the program exits.
140140
*/
@@ -368,11 +368,11 @@
368368
((B)->nUsed==sizeof(S)-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
369369
#endif
370370
371371
372372
/*
373
-** Attempt to resize a blob so that its internal buffer is
373
+** Attempt to resize a blob so that its internal buffer is
374374
** nByte in size. The blob is truncated if necessary.
375375
*/
376376
void blob_resize(Blob *pBlob, unsigned int newSize){
377377
pBlob->xRealloc(pBlob, newSize+1);
378378
pBlob->nUsed = newSize;
@@ -453,11 +453,11 @@
453453
int blob_tell(Blob *p){
454454
return p->iCursor;
455455
}
456456
457457
/*
458
-** Extract a single line of text from pFrom beginning at the current
458
+** Extract a single line of text from pFrom beginning at the current
459459
** cursor location and use that line of text to initialize pTo.
460460
** pTo will include the terminating \n. Return the number of bytes
461461
** in the line including the \n at the end. 0 is returned at
462462
** end-of-file.
463463
**
@@ -669,11 +669,11 @@
669669
void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
670670
vxprintf(pBlob, zFormat, ap);
671671
}
672672
673673
/*
674
-** Initalize a blob to the data on an input channel. Return
674
+** Initalize a blob to the data on an input channel. Return
675675
** the number of bytes read into the blob. Any prior content
676676
** of the blob is discarded, not freed.
677677
*/
678678
int blob_read_from_channel(Blob *pBlob, FILE *in, int nToRead){
679679
size_t n;
@@ -767,22 +767,16 @@
767767
int blob_write_to_file(Blob *pBlob, const char *zFilename){
768768
FILE *out;
769769
int wrote;
770770
771771
if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
772
- int n;
772
+ int n = blob_size(pBlob);
773773
#if defined(_WIN32)
774
- if( _isatty(fileno(stdout)) ){
775
- char *z;
776
- z = fossil_utf8_to_console(blob_str(pBlob));
777
- n = strlen(z);
778
- fwrite(z, 1, n, stdout);
779
- free(z);
774
+ if( fossil_utf8_to_console(blob_buffer(pBlob), n, 0) >= 0 ){
780775
return n;
781776
}
782777
#endif
783
- n = blob_size(pBlob);
784778
fwrite(blob_buffer(pBlob), 1, n, stdout);
785779
return n;
786780
}else{
787781
int i, nName;
788782
char *zName, zBuf[1000];
@@ -833,12 +827,12 @@
833827
return wrote;
834828
}
835829
836830
/*
837831
** Compress a blob pIn. Store the result in pOut. It is ok for pIn and
838
-** pOut to be the same blob.
839
-**
832
+** pOut to be the same blob.
833
+**
840834
** pOut must either be the same as pIn or else uninitialized.
841835
*/
842836
void blob_compress(Blob *pIn, Blob *pOut){
843837
unsigned int nIn = blob_size(pIn);
844838
unsigned int nOut = 13 + nIn + (nIn+999)/1000;
@@ -871,13 +865,13 @@
871865
blob_compress(&f, &f);
872866
blob_write_to_file(&f, g.argv[3]);
873867
}
874868
875869
/*
876
-** Compress the concatenation of a blobs pIn1 and pIn2. Store the result
877
-** in pOut.
878
-**
870
+** Compress the concatenation of a blobs pIn1 and pIn2. Store the result
871
+** in pOut.
872
+**
879873
** pOut must be either uninitialized or must be the same as either pIn1 or
880874
** pIn2.
881875
*/
882876
void blob_compress2(Blob *pIn1, Blob *pIn2, Blob *pOut){
883877
unsigned int nIn = blob_size(pIn1) + blob_size(pIn2);
@@ -944,11 +938,11 @@
944938
inBuf = (unsigned char*)blob_buffer(pIn);
945939
nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];
946940
blob_zero(&temp);
947941
blob_resize(&temp, nOut+1);
948942
nOut2 = (long int)nOut;
949
- rc = uncompress((unsigned char*)blob_buffer(&temp), &nOut2,
943
+ rc = uncompress((unsigned char*)blob_buffer(&temp), &nOut2,
950944
&inBuf[4], nIn - 4);
951945
if( rc!=Z_OK ){
952946
blob_reset(&temp);
953947
return 1;
954948
}
@@ -1062,11 +1056,11 @@
10621056
**
10631057
** Returns the number of bytes read/copied, which may be less than
10641058
** nLen (if end-of-blob is encountered).
10651059
**
10661060
** Updates pIn's cursor.
1067
-**
1061
+**
10681062
** Returns 0 if pIn contains no data.
10691063
*/
10701064
unsigned int blob_read(Blob *pIn, void * pDest, unsigned int nLen ){
10711065
if( !pIn->aData || (pIn->iCursor >= pIn->nUsed) ){
10721066
return 0;
10731067
--- src/blob.c
+++ src/blob.c
@@ -130,11 +130,11 @@
130 }
131
132 /*
133 ** A reallocation function that assumes that aData came from malloc().
134 ** This function attempts to resize the buffer of the blob to hold
135 ** newSize bytes.
136 **
137 ** No attempt is made to recover from an out-of-memory error.
138 ** If an OOM error occurs, an error message is printed on stderr
139 ** and the program exits.
140 */
@@ -368,11 +368,11 @@
368 ((B)->nUsed==sizeof(S)-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
369 #endif
370
371
372 /*
373 ** Attempt to resize a blob so that its internal buffer is
374 ** nByte in size. The blob is truncated if necessary.
375 */
376 void blob_resize(Blob *pBlob, unsigned int newSize){
377 pBlob->xRealloc(pBlob, newSize+1);
378 pBlob->nUsed = newSize;
@@ -453,11 +453,11 @@
453 int blob_tell(Blob *p){
454 return p->iCursor;
455 }
456
457 /*
458 ** Extract a single line of text from pFrom beginning at the current
459 ** cursor location and use that line of text to initialize pTo.
460 ** pTo will include the terminating \n. Return the number of bytes
461 ** in the line including the \n at the end. 0 is returned at
462 ** end-of-file.
463 **
@@ -669,11 +669,11 @@
669 void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
670 vxprintf(pBlob, zFormat, ap);
671 }
672
673 /*
674 ** Initalize a blob to the data on an input channel. Return
675 ** the number of bytes read into the blob. Any prior content
676 ** of the blob is discarded, not freed.
677 */
678 int blob_read_from_channel(Blob *pBlob, FILE *in, int nToRead){
679 size_t n;
@@ -767,22 +767,16 @@
767 int blob_write_to_file(Blob *pBlob, const char *zFilename){
768 FILE *out;
769 int wrote;
770
771 if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
772 int n;
773 #if defined(_WIN32)
774 if( _isatty(fileno(stdout)) ){
775 char *z;
776 z = fossil_utf8_to_console(blob_str(pBlob));
777 n = strlen(z);
778 fwrite(z, 1, n, stdout);
779 free(z);
780 return n;
781 }
782 #endif
783 n = blob_size(pBlob);
784 fwrite(blob_buffer(pBlob), 1, n, stdout);
785 return n;
786 }else{
787 int i, nName;
788 char *zName, zBuf[1000];
@@ -833,12 +827,12 @@
833 return wrote;
834 }
835
836 /*
837 ** Compress a blob pIn. Store the result in pOut. It is ok for pIn and
838 ** pOut to be the same blob.
839 **
840 ** pOut must either be the same as pIn or else uninitialized.
841 */
842 void blob_compress(Blob *pIn, Blob *pOut){
843 unsigned int nIn = blob_size(pIn);
844 unsigned int nOut = 13 + nIn + (nIn+999)/1000;
@@ -871,13 +865,13 @@
871 blob_compress(&f, &f);
872 blob_write_to_file(&f, g.argv[3]);
873 }
874
875 /*
876 ** Compress the concatenation of a blobs pIn1 and pIn2. Store the result
877 ** in pOut.
878 **
879 ** pOut must be either uninitialized or must be the same as either pIn1 or
880 ** pIn2.
881 */
882 void blob_compress2(Blob *pIn1, Blob *pIn2, Blob *pOut){
883 unsigned int nIn = blob_size(pIn1) + blob_size(pIn2);
@@ -944,11 +938,11 @@
944 inBuf = (unsigned char*)blob_buffer(pIn);
945 nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];
946 blob_zero(&temp);
947 blob_resize(&temp, nOut+1);
948 nOut2 = (long int)nOut;
949 rc = uncompress((unsigned char*)blob_buffer(&temp), &nOut2,
950 &inBuf[4], nIn - 4);
951 if( rc!=Z_OK ){
952 blob_reset(&temp);
953 return 1;
954 }
@@ -1062,11 +1056,11 @@
1062 **
1063 ** Returns the number of bytes read/copied, which may be less than
1064 ** nLen (if end-of-blob is encountered).
1065 **
1066 ** Updates pIn's cursor.
1067 **
1068 ** Returns 0 if pIn contains no data.
1069 */
1070 unsigned int blob_read(Blob *pIn, void * pDest, unsigned int nLen ){
1071 if( !pIn->aData || (pIn->iCursor >= pIn->nUsed) ){
1072 return 0;
1073
--- src/blob.c
+++ src/blob.c
@@ -130,11 +130,11 @@
130 }
131
132 /*
133 ** A reallocation function that assumes that aData came from malloc().
134 ** This function attempts to resize the buffer of the blob to hold
135 ** newSize bytes.
136 **
137 ** No attempt is made to recover from an out-of-memory error.
138 ** If an OOM error occurs, an error message is printed on stderr
139 ** and the program exits.
140 */
@@ -368,11 +368,11 @@
368 ((B)->nUsed==sizeof(S)-1 && memcmp((B)->aData,S,sizeof(S)-1)==0)
369 #endif
370
371
372 /*
373 ** Attempt to resize a blob so that its internal buffer is
374 ** nByte in size. The blob is truncated if necessary.
375 */
376 void blob_resize(Blob *pBlob, unsigned int newSize){
377 pBlob->xRealloc(pBlob, newSize+1);
378 pBlob->nUsed = newSize;
@@ -453,11 +453,11 @@
453 int blob_tell(Blob *p){
454 return p->iCursor;
455 }
456
457 /*
458 ** Extract a single line of text from pFrom beginning at the current
459 ** cursor location and use that line of text to initialize pTo.
460 ** pTo will include the terminating \n. Return the number of bytes
461 ** in the line including the \n at the end. 0 is returned at
462 ** end-of-file.
463 **
@@ -669,11 +669,11 @@
669 void blob_vappendf(Blob *pBlob, const char *zFormat, va_list ap){
670 vxprintf(pBlob, zFormat, ap);
671 }
672
673 /*
674 ** Initalize a blob to the data on an input channel. Return
675 ** the number of bytes read into the blob. Any prior content
676 ** of the blob is discarded, not freed.
677 */
678 int blob_read_from_channel(Blob *pBlob, FILE *in, int nToRead){
679 size_t n;
@@ -767,22 +767,16 @@
767 int blob_write_to_file(Blob *pBlob, const char *zFilename){
768 FILE *out;
769 int wrote;
770
771 if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
772 int n = blob_size(pBlob);
773 #if defined(_WIN32)
774 if( fossil_utf8_to_console(blob_buffer(pBlob), n, 0) >= 0 ){
 
 
 
 
 
775 return n;
776 }
777 #endif
 
778 fwrite(blob_buffer(pBlob), 1, n, stdout);
779 return n;
780 }else{
781 int i, nName;
782 char *zName, zBuf[1000];
@@ -833,12 +827,12 @@
827 return wrote;
828 }
829
830 /*
831 ** Compress a blob pIn. Store the result in pOut. It is ok for pIn and
832 ** pOut to be the same blob.
833 **
834 ** pOut must either be the same as pIn or else uninitialized.
835 */
836 void blob_compress(Blob *pIn, Blob *pOut){
837 unsigned int nIn = blob_size(pIn);
838 unsigned int nOut = 13 + nIn + (nIn+999)/1000;
@@ -871,13 +865,13 @@
865 blob_compress(&f, &f);
866 blob_write_to_file(&f, g.argv[3]);
867 }
868
869 /*
870 ** Compress the concatenation of a blobs pIn1 and pIn2. Store the result
871 ** in pOut.
872 **
873 ** pOut must be either uninitialized or must be the same as either pIn1 or
874 ** pIn2.
875 */
876 void blob_compress2(Blob *pIn1, Blob *pIn2, Blob *pOut){
877 unsigned int nIn = blob_size(pIn1) + blob_size(pIn2);
@@ -944,11 +938,11 @@
938 inBuf = (unsigned char*)blob_buffer(pIn);
939 nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];
940 blob_zero(&temp);
941 blob_resize(&temp, nOut+1);
942 nOut2 = (long int)nOut;
943 rc = uncompress((unsigned char*)blob_buffer(&temp), &nOut2,
944 &inBuf[4], nIn - 4);
945 if( rc!=Z_OK ){
946 blob_reset(&temp);
947 return 1;
948 }
@@ -1062,11 +1056,11 @@
1056 **
1057 ** Returns the number of bytes read/copied, which may be less than
1058 ** nLen (if end-of-blob is encountered).
1059 **
1060 ** Updates pIn's cursor.
1061 **
1062 ** Returns 0 if pIn contains no data.
1063 */
1064 unsigned int blob_read(Blob *pIn, void * pDest, unsigned int nLen ){
1065 if( !pIn->aData || (pIn->iCursor >= pIn->nUsed) ){
1066 return 0;
1067
+51 -28
--- src/file.c
+++ src/file.c
@@ -114,11 +114,11 @@
114114
115115
/*
116116
** Same as file_size(), but takes into account symlinks.
117117
*/
118118
i64 file_wd_size(const char *zFilename){
119
- return getStat(zFilename, 1) ? -1 : fileStat.st_size;
119
+ return getStat(zFilename, 1) ? -1 : fileStat.st_size;
120120
}
121121
122122
/*
123123
** Return the modification time for a file. Return -1 if the file
124124
** does not exist. If zFilename is NULL return the size of the most
@@ -134,11 +134,11 @@
134134
i64 file_wd_mtime(const char *zFilename){
135135
return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
136136
}
137137
138138
/*
139
-** Return TRUE if the named file is an ordinary file or symlink
139
+** Return TRUE if the named file is an ordinary file or symlink
140140
** and symlinks are allowed.
141141
** Return false for directories, devices, fifos, etc.
142142
*/
143143
int file_wd_isfile_or_link(const char *zFilename){
144144
return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
@@ -191,14 +191,14 @@
191191
}
192192
}
193193
if( zName!=zBuf ) free(zName);
194194
195195
if( symlink(zTargetFile, zName)!=0 ){
196
- fossil_fatal_recursive("unable to create symlink \"%s\"", zName);
196
+ fossil_fatal_recursive("unable to create symlink \"%s\"", zName);
197197
}
198198
}else
199
-#endif
199
+#endif
200200
{
201201
Blob content;
202202
blob_set(&content, zTargetFile);
203203
blob_write_to_file(&content, zLinkFile);
204204
blob_reset(&content);
@@ -230,11 +230,11 @@
230230
if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
231231
return PERM_EXE;
232232
else
233233
return PERM_REG;
234234
#else
235
- if( S_ISREG(fileStat.st_mode) &&
235
+ if( S_ISREG(fileStat.st_mode) &&
236236
((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0 )
237237
return PERM_EXE;
238238
else if( g.allowSymlinks && S_ISLNK(fileStat.st_mode) )
239239
return PERM_LNK;
240240
else
@@ -405,11 +405,11 @@
405405
#endif
406406
}
407407
408408
/*
409409
** Create the directory named in the argument, if it does not already
410
-** exist. If forceFlag is 1, delete any prior non-directory object
410
+** exist. If forceFlag is 1, delete any prior non-directory object
411411
** with the same name.
412412
**
413413
** Return the number of errors.
414414
*/
415415
int file_mkdir(const char *zName, int forceFlag){
@@ -719,11 +719,11 @@
719719
}
720720
}
721721
return 1;
722722
}
723723
724
-/*
724
+/*
725725
** Return a pointer to the first character in a pathname past the
726726
** drive letter. This routine is a no-op on unix.
727727
*/
728728
char *file_without_drive_letter(char *zIn){
729729
#ifdef _WIN32
@@ -947,19 +947,19 @@
947947
948948
azDirs[1] = fossil_getenv("TEMP");
949949
azDirs[2] = fossil_getenv("TMP");
950950
#endif
951951
952
-
952
+
953953
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
954954
if( azDirs[i]==0 ) continue;
955955
if( !file_isdir(azDirs[i]) ) continue;
956956
zDir = azDirs[i];
957957
break;
958958
}
959959
960
- /* Check that the output buffer is large enough for the temporary file
960
+ /* Check that the output buffer is large enough for the temporary file
961961
** name. If it is not, return SQLITE_ERROR.
962962
*/
963963
if( (strlen(zDir) + 17) >= (size_t)nBuf ){
964964
fossil_fatal("insufficient space for temporary filename");
965965
}
@@ -1035,21 +1035,21 @@
10351035
** Since everything is always UTF8 on unix, these routines are no-ops
10361036
** there.
10371037
*/
10381038
10391039
/*
1040
-** Translate MBCS to UTF8. Return a pointer to the translated text.
1040
+** Translate MBCS to UTF8. Return a pointer to the translated text.
10411041
** Call fossil_mbcs_free() to deallocate any memory used to store the
10421042
** returned pointer when done.
10431043
*/
10441044
char *fossil_mbcs_to_utf8(const char *zMbcs){
10451045
#ifdef _WIN32
10461046
extern char *sqlite3_win32_mbcs_to_utf8(const char*);
10471047
return sqlite3_win32_mbcs_to_utf8(zMbcs);
10481048
#else
10491049
return (char*)zMbcs; /* No-op on unix */
1050
-#endif
1050
+#endif
10511051
}
10521052
10531053
/*
10541054
** Translate Unicode to UTF8. Return a pointer to the translated text.
10551055
** Call fossil_mbcs_free() to deallocate any memory used to store the
@@ -1078,11 +1078,11 @@
10781078
#ifdef _WIN32
10791079
extern char *sqlite3_win32_utf8_to_mbcs(const char*);
10801080
return sqlite3_win32_utf8_to_mbcs(zUtf8);
10811081
#else
10821082
return (char*)zUtf8; /* No-op on unix */
1083
-#endif
1083
+#endif
10841084
}
10851085
10861086
/*
10871087
** Translate UTF8 to unicode for use in system calls. Return a pointer to the
10881088
** translated text.. Call fossil_mbcs_free() to deallocate any memory
@@ -1116,48 +1116,71 @@
11161116
#endif
11171117
return zValue;
11181118
}
11191119
11201120
/*
1121
-** Translate UTF8 to MBCS for display on the console. Return a pointer to the
1122
-** translated text.. Call fossil_mbcs_free() to deallocate any memory
1123
-** used to store the returned pointer when done.
1121
+** Display UTF8 on the console. Return the number of
1122
+** Characters written. If stdout or stderr is redirected
1123
+** to a file, -1 is returned and nothing is written
1124
+** to the console.
11241125
*/
1125
-char *fossil_utf8_to_console(const char *zUtf8){
1126
+int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
11261127
#ifdef _WIN32
1127
- int nChar, nByte;
1128
- WCHAR *zUnicode; /* Unicode version of zUtf8 */
1128
+ int nChar;
1129
+ wchar_t *zUnicode; /* Unicode version of zUtf8 */
1130
+#ifdef UNICODE
1131
+ DWORD dummy;
1132
+#else
11291133
char *zConsole; /* Console version of zUtf8 */
11301134
int codepage; /* Console code page */
1135
+#endif
1136
+
1137
+ static int istty[2] = { -1, -1 };
1138
+ if( istty[toStdErr] == -1 ){
1139
+ istty[toStdErr] = _isatty(toStdErr + 1) != 0;
1140
+ }
1141
+ if( !istty[toStdErr] ){
1142
+ /* stdout/stderr is not a console. */
1143
+ return -1;
1144
+ }
11311145
1132
- nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0);
1133
- zUnicode = malloc( nChar*sizeof(zUnicode[0]) );
1146
+ nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, nByte, NULL, 0);
1147
+ zUnicode = malloc( (nChar + 1) *sizeof(zUnicode[0]) );
11341148
if( zUnicode==0 ){
11351149
return 0;
11361150
}
1137
- nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
1151
+ nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, nByte, zUnicode, nChar);
11381152
if( nChar==0 ){
11391153
free(zUnicode);
11401154
return 0;
11411155
}
1156
+ zUnicode[nChar] = '\0';
1157
+#ifdef UNICODE
1158
+ WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE - toStdErr), zUnicode, nChar, &dummy, 0);
1159
+#else /* !UNICODE */
11421160
codepage = GetConsoleCP();
1143
- nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, 0, 0, 0, 0);
1144
- zConsole = malloc( nByte );
1161
+ nByte = WideCharToMultiByte(codepage, 0, zUnicode, nChar, 0, 0, 0, 0);
1162
+ zConsole = malloc( nByte + 1);
11451163
if( zConsole==0 ){
11461164
free(zUnicode);
11471165
return 0;
11481166
}
1149
- nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, zConsole, nByte, 0, 0);
1167
+ nByte = WideCharToMultiByte(codepage, 0, zUnicode, nChar, zConsole, nByte, 0, 0);
1168
+ zConsole[nByte] = '\0';
11501169
free(zUnicode);
11511170
if( nByte == 0 ){
11521171
free(zConsole);
11531172
zConsole = 0;
1173
+ return 0;
11541174
}
1155
- return zConsole;
1175
+ fwrite(zConsole, 1, nByte, toStdErr ? stderr : stdout);
1176
+ fflush(toStdErr ? stderr : stdout);
1177
+#endif /* UNICODE */
1178
+ return nChar;
11561179
#else
1157
- return (char*)zUtf8; /* No-op on unix */
1158
-#endif
1180
+ return -1; /* No-op on unix */
1181
+#endif
11591182
}
11601183
11611184
/*
11621185
** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free()
11631186
** to deallocate any memory used to store the returned pointer when done.
@@ -1166,11 +1189,11 @@
11661189
#ifdef _WIN32
11671190
extern void sqlite3_free(void*);
11681191
sqlite3_free(zOld);
11691192
#else
11701193
/* No-op on unix */
1171
-#endif
1194
+#endif
11721195
}
11731196
11741197
/*
11751198
** Like fopen() but always takes a UTF8 argument.
11761199
*/
11771200
--- src/file.c
+++ src/file.c
@@ -114,11 +114,11 @@
114
115 /*
116 ** Same as file_size(), but takes into account symlinks.
117 */
118 i64 file_wd_size(const char *zFilename){
119 return getStat(zFilename, 1) ? -1 : fileStat.st_size;
120 }
121
122 /*
123 ** Return the modification time for a file. Return -1 if the file
124 ** does not exist. If zFilename is NULL return the size of the most
@@ -134,11 +134,11 @@
134 i64 file_wd_mtime(const char *zFilename){
135 return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
136 }
137
138 /*
139 ** Return TRUE if the named file is an ordinary file or symlink
140 ** and symlinks are allowed.
141 ** Return false for directories, devices, fifos, etc.
142 */
143 int file_wd_isfile_or_link(const char *zFilename){
144 return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
@@ -191,14 +191,14 @@
191 }
192 }
193 if( zName!=zBuf ) free(zName);
194
195 if( symlink(zTargetFile, zName)!=0 ){
196 fossil_fatal_recursive("unable to create symlink \"%s\"", zName);
197 }
198 }else
199 #endif
200 {
201 Blob content;
202 blob_set(&content, zTargetFile);
203 blob_write_to_file(&content, zLinkFile);
204 blob_reset(&content);
@@ -230,11 +230,11 @@
230 if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
231 return PERM_EXE;
232 else
233 return PERM_REG;
234 #else
235 if( S_ISREG(fileStat.st_mode) &&
236 ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0 )
237 return PERM_EXE;
238 else if( g.allowSymlinks && S_ISLNK(fileStat.st_mode) )
239 return PERM_LNK;
240 else
@@ -405,11 +405,11 @@
405 #endif
406 }
407
408 /*
409 ** Create the directory named in the argument, if it does not already
410 ** exist. If forceFlag is 1, delete any prior non-directory object
411 ** with the same name.
412 **
413 ** Return the number of errors.
414 */
415 int file_mkdir(const char *zName, int forceFlag){
@@ -719,11 +719,11 @@
719 }
720 }
721 return 1;
722 }
723
724 /*
725 ** Return a pointer to the first character in a pathname past the
726 ** drive letter. This routine is a no-op on unix.
727 */
728 char *file_without_drive_letter(char *zIn){
729 #ifdef _WIN32
@@ -947,19 +947,19 @@
947
948 azDirs[1] = fossil_getenv("TEMP");
949 azDirs[2] = fossil_getenv("TMP");
950 #endif
951
952
953 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
954 if( azDirs[i]==0 ) continue;
955 if( !file_isdir(azDirs[i]) ) continue;
956 zDir = azDirs[i];
957 break;
958 }
959
960 /* Check that the output buffer is large enough for the temporary file
961 ** name. If it is not, return SQLITE_ERROR.
962 */
963 if( (strlen(zDir) + 17) >= (size_t)nBuf ){
964 fossil_fatal("insufficient space for temporary filename");
965 }
@@ -1035,21 +1035,21 @@
1035 ** Since everything is always UTF8 on unix, these routines are no-ops
1036 ** there.
1037 */
1038
1039 /*
1040 ** Translate MBCS to UTF8. Return a pointer to the translated text.
1041 ** Call fossil_mbcs_free() to deallocate any memory used to store the
1042 ** returned pointer when done.
1043 */
1044 char *fossil_mbcs_to_utf8(const char *zMbcs){
1045 #ifdef _WIN32
1046 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
1047 return sqlite3_win32_mbcs_to_utf8(zMbcs);
1048 #else
1049 return (char*)zMbcs; /* No-op on unix */
1050 #endif
1051 }
1052
1053 /*
1054 ** Translate Unicode to UTF8. Return a pointer to the translated text.
1055 ** Call fossil_mbcs_free() to deallocate any memory used to store the
@@ -1078,11 +1078,11 @@
1078 #ifdef _WIN32
1079 extern char *sqlite3_win32_utf8_to_mbcs(const char*);
1080 return sqlite3_win32_utf8_to_mbcs(zUtf8);
1081 #else
1082 return (char*)zUtf8; /* No-op on unix */
1083 #endif
1084 }
1085
1086 /*
1087 ** Translate UTF8 to unicode for use in system calls. Return a pointer to the
1088 ** translated text.. Call fossil_mbcs_free() to deallocate any memory
@@ -1116,48 +1116,71 @@
1116 #endif
1117 return zValue;
1118 }
1119
1120 /*
1121 ** Translate UTF8 to MBCS for display on the console. Return a pointer to the
1122 ** translated text.. Call fossil_mbcs_free() to deallocate any memory
1123 ** used to store the returned pointer when done.
 
1124 */
1125 char *fossil_utf8_to_console(const char *zUtf8){
1126 #ifdef _WIN32
1127 int nChar, nByte;
1128 WCHAR *zUnicode; /* Unicode version of zUtf8 */
 
 
 
1129 char *zConsole; /* Console version of zUtf8 */
1130 int codepage; /* Console code page */
 
 
 
 
 
 
 
 
 
 
1131
1132 nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, NULL, 0);
1133 zUnicode = malloc( nChar*sizeof(zUnicode[0]) );
1134 if( zUnicode==0 ){
1135 return 0;
1136 }
1137 nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
1138 if( nChar==0 ){
1139 free(zUnicode);
1140 return 0;
1141 }
 
 
 
 
1142 codepage = GetConsoleCP();
1143 nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, 0, 0, 0, 0);
1144 zConsole = malloc( nByte );
1145 if( zConsole==0 ){
1146 free(zUnicode);
1147 return 0;
1148 }
1149 nByte = WideCharToMultiByte(codepage, 0, zUnicode, -1, zConsole, nByte, 0, 0);
 
1150 free(zUnicode);
1151 if( nByte == 0 ){
1152 free(zConsole);
1153 zConsole = 0;
 
1154 }
1155 return zConsole;
 
 
 
1156 #else
1157 return (char*)zUtf8; /* No-op on unix */
1158 #endif
1159 }
1160
1161 /*
1162 ** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free()
1163 ** to deallocate any memory used to store the returned pointer when done.
@@ -1166,11 +1189,11 @@
1166 #ifdef _WIN32
1167 extern void sqlite3_free(void*);
1168 sqlite3_free(zOld);
1169 #else
1170 /* No-op on unix */
1171 #endif
1172 }
1173
1174 /*
1175 ** Like fopen() but always takes a UTF8 argument.
1176 */
1177
--- src/file.c
+++ src/file.c
@@ -114,11 +114,11 @@
114
115 /*
116 ** Same as file_size(), but takes into account symlinks.
117 */
118 i64 file_wd_size(const char *zFilename){
119 return getStat(zFilename, 1) ? -1 : fileStat.st_size;
120 }
121
122 /*
123 ** Return the modification time for a file. Return -1 if the file
124 ** does not exist. If zFilename is NULL return the size of the most
@@ -134,11 +134,11 @@
134 i64 file_wd_mtime(const char *zFilename){
135 return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
136 }
137
138 /*
139 ** Return TRUE if the named file is an ordinary file or symlink
140 ** and symlinks are allowed.
141 ** Return false for directories, devices, fifos, etc.
142 */
143 int file_wd_isfile_or_link(const char *zFilename){
144 return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
@@ -191,14 +191,14 @@
191 }
192 }
193 if( zName!=zBuf ) free(zName);
194
195 if( symlink(zTargetFile, zName)!=0 ){
196 fossil_fatal_recursive("unable to create symlink \"%s\"", zName);
197 }
198 }else
199 #endif
200 {
201 Blob content;
202 blob_set(&content, zTargetFile);
203 blob_write_to_file(&content, zLinkFile);
204 blob_reset(&content);
@@ -230,11 +230,11 @@
230 if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
231 return PERM_EXE;
232 else
233 return PERM_REG;
234 #else
235 if( S_ISREG(fileStat.st_mode) &&
236 ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0 )
237 return PERM_EXE;
238 else if( g.allowSymlinks && S_ISLNK(fileStat.st_mode) )
239 return PERM_LNK;
240 else
@@ -405,11 +405,11 @@
405 #endif
406 }
407
408 /*
409 ** Create the directory named in the argument, if it does not already
410 ** exist. If forceFlag is 1, delete any prior non-directory object
411 ** with the same name.
412 **
413 ** Return the number of errors.
414 */
415 int file_mkdir(const char *zName, int forceFlag){
@@ -719,11 +719,11 @@
719 }
720 }
721 return 1;
722 }
723
724 /*
725 ** Return a pointer to the first character in a pathname past the
726 ** drive letter. This routine is a no-op on unix.
727 */
728 char *file_without_drive_letter(char *zIn){
729 #ifdef _WIN32
@@ -947,19 +947,19 @@
947
948 azDirs[1] = fossil_getenv("TEMP");
949 azDirs[2] = fossil_getenv("TMP");
950 #endif
951
952
953 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
954 if( azDirs[i]==0 ) continue;
955 if( !file_isdir(azDirs[i]) ) continue;
956 zDir = azDirs[i];
957 break;
958 }
959
960 /* Check that the output buffer is large enough for the temporary file
961 ** name. If it is not, return SQLITE_ERROR.
962 */
963 if( (strlen(zDir) + 17) >= (size_t)nBuf ){
964 fossil_fatal("insufficient space for temporary filename");
965 }
@@ -1035,21 +1035,21 @@
1035 ** Since everything is always UTF8 on unix, these routines are no-ops
1036 ** there.
1037 */
1038
1039 /*
1040 ** Translate MBCS to UTF8. Return a pointer to the translated text.
1041 ** Call fossil_mbcs_free() to deallocate any memory used to store the
1042 ** returned pointer when done.
1043 */
1044 char *fossil_mbcs_to_utf8(const char *zMbcs){
1045 #ifdef _WIN32
1046 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
1047 return sqlite3_win32_mbcs_to_utf8(zMbcs);
1048 #else
1049 return (char*)zMbcs; /* No-op on unix */
1050 #endif
1051 }
1052
1053 /*
1054 ** Translate Unicode to UTF8. Return a pointer to the translated text.
1055 ** Call fossil_mbcs_free() to deallocate any memory used to store the
@@ -1078,11 +1078,11 @@
1078 #ifdef _WIN32
1079 extern char *sqlite3_win32_utf8_to_mbcs(const char*);
1080 return sqlite3_win32_utf8_to_mbcs(zUtf8);
1081 #else
1082 return (char*)zUtf8; /* No-op on unix */
1083 #endif
1084 }
1085
1086 /*
1087 ** Translate UTF8 to unicode for use in system calls. Return a pointer to the
1088 ** translated text.. Call fossil_mbcs_free() to deallocate any memory
@@ -1116,48 +1116,71 @@
1116 #endif
1117 return zValue;
1118 }
1119
1120 /*
1121 ** Display UTF8 on the console. Return the number of
1122 ** Characters written. If stdout or stderr is redirected
1123 ** to a file, -1 is returned and nothing is written
1124 ** to the console.
1125 */
1126 int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
1127 #ifdef _WIN32
1128 int nChar;
1129 wchar_t *zUnicode; /* Unicode version of zUtf8 */
1130 #ifdef UNICODE
1131 DWORD dummy;
1132 #else
1133 char *zConsole; /* Console version of zUtf8 */
1134 int codepage; /* Console code page */
1135 #endif
1136
1137 static int istty[2] = { -1, -1 };
1138 if( istty[toStdErr] == -1 ){
1139 istty[toStdErr] = _isatty(toStdErr + 1) != 0;
1140 }
1141 if( !istty[toStdErr] ){
1142 /* stdout/stderr is not a console. */
1143 return -1;
1144 }
1145
1146 nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, nByte, NULL, 0);
1147 zUnicode = malloc( (nChar + 1) *sizeof(zUnicode[0]) );
1148 if( zUnicode==0 ){
1149 return 0;
1150 }
1151 nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, nByte, zUnicode, nChar);
1152 if( nChar==0 ){
1153 free(zUnicode);
1154 return 0;
1155 }
1156 zUnicode[nChar] = '\0';
1157 #ifdef UNICODE
1158 WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE - toStdErr), zUnicode, nChar, &dummy, 0);
1159 #else /* !UNICODE */
1160 codepage = GetConsoleCP();
1161 nByte = WideCharToMultiByte(codepage, 0, zUnicode, nChar, 0, 0, 0, 0);
1162 zConsole = malloc( nByte + 1);
1163 if( zConsole==0 ){
1164 free(zUnicode);
1165 return 0;
1166 }
1167 nByte = WideCharToMultiByte(codepage, 0, zUnicode, nChar, zConsole, nByte, 0, 0);
1168 zConsole[nByte] = '\0';
1169 free(zUnicode);
1170 if( nByte == 0 ){
1171 free(zConsole);
1172 zConsole = 0;
1173 return 0;
1174 }
1175 fwrite(zConsole, 1, nByte, toStdErr ? stderr : stdout);
1176 fflush(toStdErr ? stderr : stdout);
1177 #endif /* UNICODE */
1178 return nChar;
1179 #else
1180 return -1; /* No-op on unix */
1181 #endif
1182 }
1183
1184 /*
1185 ** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free()
1186 ** to deallocate any memory used to store the returned pointer when done.
@@ -1166,11 +1189,11 @@
1189 #ifdef _WIN32
1190 extern void sqlite3_free(void*);
1191 sqlite3_free(zOld);
1192 #else
1193 /* No-op on unix */
1194 #endif
1195 }
1196
1197 /*
1198 ** Like fopen() but always takes a UTF8 argument.
1199 */
1200
+149 -22
--- src/main.c
+++ src/main.c
@@ -157,11 +157,11 @@
157157
char *urlPasswd; /* Password for http: */
158158
char *urlCanonical; /* Canonical representation of the URL */
159159
char *urlProxyAuth; /* Proxy-Authorizer: string */
160160
char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
161161
int dontKeepUrl; /* Do not persist the URL */
162
-
162
+
163163
const char *zLogin; /* Login name. "" if not logged in. */
164164
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
165165
int useLocalauth; /* No login required if from 127.0.0.1 */
166166
int noPswd; /* Logged in without password (on 127.0.0.1) */
167167
int userUid; /* Integer user id */
@@ -168,11 +168,11 @@
168168
169169
/* Information used to populate the RCVFROM table */
170170
int rcvid; /* The rcvid. 0 if not yet defined. */
171171
char *zIpAddr; /* The remote IP address */
172172
char *zNonce; /* The nonce used for login */
173
-
173
+
174174
/* permissions used by the server */
175175
struct FossilUserPerms perm;
176176
177177
#ifdef FOSSIL_ENABLE_TCL
178178
/* all Tcl related context necessary for integration */
@@ -195,11 +195,11 @@
195195
const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */
196196
char *azAuxParam[MX_AUX]; /* Param of each aux() or option() value */
197197
const char *azAuxVal[MX_AUX]; /* Value of each aux() or option() value */
198198
const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
199199
int anAuxCols[MX_AUX]; /* Number of columns for option() values */
200
-
200
+
201201
int allowSymlinks; /* Cached "allow-symlinks" option */
202202
203203
#ifdef FOSSIL_ENABLE_JSON
204204
struct FossilJsonBits {
205205
int isJsonMode; /* True if running in JSON mode, else
@@ -262,11 +262,11 @@
262262
#endif
263263
264264
Global g;
265265
266266
/*
267
-** The table of web pages supported by this application is generated
267
+** The table of web pages supported by this application is generated
268268
** automatically by the "mkindex" program and written into a file
269269
** named "page_index.h". We include that file here to get access
270270
** to the table.
271271
*/
272272
#include "page_index.h"
@@ -329,30 +329,147 @@
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 from mbcs to UTF-8. Then
453
+** Convert all arguments from mbcs (or unicode) to UTF-8. Then
337454
** 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
343460
** (c) If the line begins with "-" and contains a space, it is broken
344461
** into two arguments at the space.
345462
*/
346
-static void expand_args_option(int argc, char **argv){
463
+static void expand_args_option(int argc, void *argv){
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,13 +476,18 @@
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);
484
+#ifdef UNICODE
485
+ for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
486
+#else
366487
for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
488
+#endif
367489
#endif
368490
for(i=1; i<g.argc-1; i++){
369491
z = g.argv[i];
370492
if( z[0]!='-' ) continue;
371493
z++;
@@ -390,21 +512,21 @@
390512
}
391513
z = blob_str(&file);
392514
for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
393515
newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
394516
for(j=0; j<i; j++) newArgv[j] = g.argv[j];
395
-
517
+
396518
blob_rewind(&file);
397519
while( (n = blob_line(&file, &line))>0 ){
398520
if( n<=1 ) continue;
399521
z = blob_buffer(&line);
400522
z[n-1] = 0;
401523
if (foundBom == -1) {
402524
static const char bom[] = { 0xEF, 0xBB, 0xBF };
403525
foundBom = memcmp(z, bom, 3)==0;
404526
if( foundBom ) {
405
- z += 3; n -= 3;
527
+ z += 3; n -= 3;
406528
}
407529
}
408530
if((n>1) && ('\r'==z[n-2])){
409531
if(n==2) continue /*empty line*/;
410532
z[n-2] = 0;
@@ -430,11 +552,16 @@
430552
}
431553
432554
/*
433555
** This procedure runs first.
434556
*/
435
-int main(int argc, char **argv){
557
+#if defined(_WIN32) && defined(UNICODE)
558
+int wmain(int argc, wchar_t **argv)
559
+#else
560
+int main(int argc, char **argv)
561
+#endif
562
+{
436563
const char *zCmdName = "unknown";
437564
int idx;
438565
int rc;
439566
440567
sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -726,12 +853,12 @@
726853
#else
727854
/* On unix, evaluate the command directly.
728855
*/
729856
if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
730857
rc = system(zOrigCmd);
731
-#endif
732
- return rc;
858
+#endif
859
+ return rc;
733860
}
734861
735862
/*
736863
** Turn off any NL to CRNL translation on the stream given as an
737864
** argument. This is a no-op on unix but is necessary on windows.
@@ -1194,11 +1321,11 @@
11941321
** * Environment variables are set up according to the CGI standard.
11951322
**
11961323
** If the repository is known, it has already been opened. If unknown,
11971324
** then g.zRepositoryName holds the directory that contains the repository
11981325
** and the actual repository is taken from the first element of PATH_INFO.
1199
-**
1326
+**
12001327
** Process the webpage specified by the PATH_INFO or REQUEST_URI
12011328
** environment variable.
12021329
*/
12031330
static void process_one_web_page(const char *zNotFound){
12041331
const char *zPathInfo;
@@ -1267,11 +1394,11 @@
12671394
cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
12681395
zPathInfo += i;
12691396
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
12701397
db_open_repository(zRepo);
12711398
if( g.fHttpTrace ){
1272
- fprintf(stderr,
1399
+ fprintf(stderr,
12731400
"# repository: [%s]\n"
12741401
"# new PATH_INFO = [%s]\n"
12751402
"# new SCRIPT_NAME = [%s]\n",
12761403
zRepo, zPathInfo, zNewScript);
12771404
}
@@ -1282,11 +1409,11 @@
12821409
*/
12831410
if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
12841411
zPathInfo = "/xfer";
12851412
}
12861413
set_base_url();
1287
- if( zPathInfo==0 || zPathInfo[0]==0
1414
+ if( zPathInfo==0 || zPathInfo[0]==0
12881415
|| (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
12891416
#ifdef FOSSIL_ENABLE_JSON
12901417
if(g.json.isJsonMode){
12911418
json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
12921419
fossil_exit(0);
@@ -1312,11 +1439,11 @@
13121439
** that accepts the login credentials of the current repository. A
13131440
** subrepository is identified by a CONFIG table entry "subrepo:NAME"
13141441
** where NAME is the first component of the path. The value of the
13151442
** the CONFIG entries is the string "USER:FILENAME" where USER is the
13161443
** USER name to log in as in the subrepository and FILENAME is the
1317
- ** repository filename.
1444
+ ** repository filename.
13181445
*/
13191446
zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
13201447
g.zPath);
13211448
if( zAltRepo ){
13221449
int nHost;
@@ -1514,11 +1641,11 @@
15141641
15151642
/* If the CGI program contains one or more lines of the form
15161643
**
15171644
** redirect: repository-filename http://hostname/path/%s
15181645
**
1519
-** then control jumps here. Search each repository for an artifact ID
1646
+** then control jumps here. Search each repository for an artifact ID
15201647
** that matches the "name" CGI parameter and for the first match,
15211648
** redirect to the corresponding URL with the "name" CGI parameter
15221649
** inserted. Paint an error page if no match is found.
15231650
**
15241651
** If there is a line of the form:
@@ -1530,11 +1657,11 @@
15301657
*/
15311658
void redirect_web_page(int nRedirect, char **azRedirect){
15321659
int i; /* Loop counter */
15331660
const char *zNotFound = 0; /* Not found URL */
15341661
const char *zName = P("name");
1535
- set_base_url();
1662
+ set_base_url();
15361663
if( zName==0 ){
15371664
zName = P("SCRIPT_NAME");
15381665
if( zName && zName[0]=='/' ) zName++;
15391666
}
15401667
if( zName && validate16(zName, strlen(zName)) ){
@@ -1603,11 +1730,11 @@
16031730
**
16041731
** Usage: %fossil http REPOSITORY ?OPTIONS?
16051732
**
16061733
** Handle a single HTTP request appearing on stdin. The resulting webpage
16071734
** is delivered on stdout. This method is used to launch an HTTP request
1608
-** handler from inetd, for example. The argument is the name of the
1735
+** handler from inetd, for example. The argument is the name of the
16091736
** repository.
16101737
**
16111738
** If REPOSITORY is a directory that contains one or more repositories
16121739
** with names of the form "*.fossil" then the first element of the URL
16131740
** pathname selects among the various repositories. If the pathname does
@@ -1742,11 +1869,11 @@
17421869
** See also: cgi, http, winsrv
17431870
*/
17441871
void cmd_webserver(void){
17451872
int iPort, mxPort; /* Range of TCP ports allowed */
17461873
const char *zPort; /* Value of the --port option */
1747
- char *zBrowser; /* Name of web browser program */
1874
+ const char *zBrowser; /* Name of web browser program */
17481875
char *zBrowserCmd = 0; /* Command to launch the web browser */
17491876
int isUiCmd; /* True if command is "ui", not "server' */
17501877
const char *zNotFound; /* The --notfound option or NULL */
17511878
int flags = 0; /* Server flags */
17521879
@@ -1779,11 +1906,11 @@
17791906
/* Unix implementation */
17801907
if( isUiCmd ){
17811908
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17821909
zBrowser = db_get("web-browser", 0);
17831910
if( zBrowser==0 ){
1784
- static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1911
+ static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
17851912
int i;
17861913
zBrowser = "echo";
17871914
for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
17881915
if( binaryOnPath(azBrowserProg[i]) ){
17891916
zBrowser = azBrowserProg[i];
17901917
--- src/main.c
+++ src/main.c
@@ -157,11 +157,11 @@
157 char *urlPasswd; /* Password for http: */
158 char *urlCanonical; /* Canonical representation of the URL */
159 char *urlProxyAuth; /* Proxy-Authorizer: string */
160 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
161 int dontKeepUrl; /* Do not persist the URL */
162
163 const char *zLogin; /* Login name. "" if not logged in. */
164 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
165 int useLocalauth; /* No login required if from 127.0.0.1 */
166 int noPswd; /* Logged in without password (on 127.0.0.1) */
167 int userUid; /* Integer user id */
@@ -168,11 +168,11 @@
168
169 /* Information used to populate the RCVFROM table */
170 int rcvid; /* The rcvid. 0 if not yet defined. */
171 char *zIpAddr; /* The remote IP address */
172 char *zNonce; /* The nonce used for login */
173
174 /* permissions used by the server */
175 struct FossilUserPerms perm;
176
177 #ifdef FOSSIL_ENABLE_TCL
178 /* all Tcl related context necessary for integration */
@@ -195,11 +195,11 @@
195 const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */
196 char *azAuxParam[MX_AUX]; /* Param of each aux() or option() value */
197 const char *azAuxVal[MX_AUX]; /* Value of each aux() or option() value */
198 const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
199 int anAuxCols[MX_AUX]; /* Number of columns for option() values */
200
201 int allowSymlinks; /* Cached "allow-symlinks" option */
202
203 #ifdef FOSSIL_ENABLE_JSON
204 struct FossilJsonBits {
205 int isJsonMode; /* True if running in JSON mode, else
@@ -262,11 +262,11 @@
262 #endif
263
264 Global g;
265
266 /*
267 ** The table of web pages supported by this application is generated
268 ** automatically by the "mkindex" program and written into a file
269 ** named "page_index.h". We include that file here to get access
270 ** to the table.
271 */
272 #include "page_index.h"
@@ -329,30 +329,147 @@
329 free(g.zErrMsg);
330 if(g.db){
331 db_close(0);
332 }
333 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
335 /*
336 ** Convert all arguments from mbcs to UTF-8. Then
337 ** search g.argv for arguments "--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
343 ** (c) If the line begins with "-" and contains a space, it is broken
344 ** into two arguments at the space.
345 */
346 static void expand_args_option(int argc, char **argv){
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,13 +476,18 @@
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
368 for(i=1; i<g.argc-1; i++){
369 z = g.argv[i];
370 if( z[0]!='-' ) continue;
371 z++;
@@ -390,21 +512,21 @@
390 }
391 z = blob_str(&file);
392 for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
393 newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
394 for(j=0; j<i; j++) newArgv[j] = g.argv[j];
395
396 blob_rewind(&file);
397 while( (n = blob_line(&file, &line))>0 ){
398 if( n<=1 ) continue;
399 z = blob_buffer(&line);
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 }
408 if((n>1) && ('\r'==z[n-2])){
409 if(n==2) continue /*empty line*/;
410 z[n-2] = 0;
@@ -430,11 +552,16 @@
430 }
431
432 /*
433 ** This procedure runs first.
434 */
435 int main(int argc, char **argv){
 
 
 
 
 
436 const char *zCmdName = "unknown";
437 int idx;
438 int rc;
439
440 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -726,12 +853,12 @@
726 #else
727 /* On unix, evaluate the command directly.
728 */
729 if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
730 rc = system(zOrigCmd);
731 #endif
732 return rc;
733 }
734
735 /*
736 ** Turn off any NL to CRNL translation on the stream given as an
737 ** argument. This is a no-op on unix but is necessary on windows.
@@ -1194,11 +1321,11 @@
1194 ** * Environment variables are set up according to the CGI standard.
1195 **
1196 ** If the repository is known, it has already been opened. If unknown,
1197 ** then g.zRepositoryName holds the directory that contains the repository
1198 ** and the actual repository is taken from the first element of PATH_INFO.
1199 **
1200 ** Process the webpage specified by the PATH_INFO or REQUEST_URI
1201 ** environment variable.
1202 */
1203 static void process_one_web_page(const char *zNotFound){
1204 const char *zPathInfo;
@@ -1267,11 +1394,11 @@
1267 cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
1268 zPathInfo += i;
1269 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1270 db_open_repository(zRepo);
1271 if( g.fHttpTrace ){
1272 fprintf(stderr,
1273 "# repository: [%s]\n"
1274 "# new PATH_INFO = [%s]\n"
1275 "# new SCRIPT_NAME = [%s]\n",
1276 zRepo, zPathInfo, zNewScript);
1277 }
@@ -1282,11 +1409,11 @@
1282 */
1283 if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
1284 zPathInfo = "/xfer";
1285 }
1286 set_base_url();
1287 if( zPathInfo==0 || zPathInfo[0]==0
1288 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
1289 #ifdef FOSSIL_ENABLE_JSON
1290 if(g.json.isJsonMode){
1291 json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
1292 fossil_exit(0);
@@ -1312,11 +1439,11 @@
1312 ** that accepts the login credentials of the current repository. A
1313 ** subrepository is identified by a CONFIG table entry "subrepo:NAME"
1314 ** where NAME is the first component of the path. The value of the
1315 ** the CONFIG entries is the string "USER:FILENAME" where USER is the
1316 ** USER name to log in as in the subrepository and FILENAME is the
1317 ** repository filename.
1318 */
1319 zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
1320 g.zPath);
1321 if( zAltRepo ){
1322 int nHost;
@@ -1514,11 +1641,11 @@
1514
1515 /* If the CGI program contains one or more lines of the form
1516 **
1517 ** redirect: repository-filename http://hostname/path/%s
1518 **
1519 ** then control jumps here. Search each repository for an artifact ID
1520 ** that matches the "name" CGI parameter and for the first match,
1521 ** redirect to the corresponding URL with the "name" CGI parameter
1522 ** inserted. Paint an error page if no match is found.
1523 **
1524 ** If there is a line of the form:
@@ -1530,11 +1657,11 @@
1530 */
1531 void redirect_web_page(int nRedirect, char **azRedirect){
1532 int i; /* Loop counter */
1533 const char *zNotFound = 0; /* Not found URL */
1534 const char *zName = P("name");
1535 set_base_url();
1536 if( zName==0 ){
1537 zName = P("SCRIPT_NAME");
1538 if( zName && zName[0]=='/' ) zName++;
1539 }
1540 if( zName && validate16(zName, strlen(zName)) ){
@@ -1603,11 +1730,11 @@
1603 **
1604 ** Usage: %fossil http REPOSITORY ?OPTIONS?
1605 **
1606 ** Handle a single HTTP request appearing on stdin. The resulting webpage
1607 ** is delivered on stdout. This method is used to launch an HTTP request
1608 ** handler from inetd, for example. The argument is the name of the
1609 ** repository.
1610 **
1611 ** If REPOSITORY is a directory that contains one or more repositories
1612 ** with names of the form "*.fossil" then the first element of the URL
1613 ** pathname selects among the various repositories. If the pathname does
@@ -1742,11 +1869,11 @@
1742 ** See also: cgi, http, winsrv
1743 */
1744 void cmd_webserver(void){
1745 int iPort, mxPort; /* Range of TCP ports allowed */
1746 const char *zPort; /* Value of the --port option */
1747 char *zBrowser; /* Name of web browser program */
1748 char *zBrowserCmd = 0; /* Command to launch the web browser */
1749 int isUiCmd; /* True if command is "ui", not "server' */
1750 const char *zNotFound; /* The --notfound option or NULL */
1751 int flags = 0; /* Server flags */
1752
@@ -1779,11 +1906,11 @@
1779 /* Unix implementation */
1780 if( isUiCmd ){
1781 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1782 zBrowser = db_get("web-browser", 0);
1783 if( zBrowser==0 ){
1784 static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1785 int i;
1786 zBrowser = "echo";
1787 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1788 if( binaryOnPath(azBrowserProg[i]) ){
1789 zBrowser = azBrowserProg[i];
1790
--- src/main.c
+++ src/main.c
@@ -157,11 +157,11 @@
157 char *urlPasswd; /* Password for http: */
158 char *urlCanonical; /* Canonical representation of the URL */
159 char *urlProxyAuth; /* Proxy-Authorizer: string */
160 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */
161 int dontKeepUrl; /* Do not persist the URL */
162
163 const char *zLogin; /* Login name. "" if not logged in. */
164 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
165 int useLocalauth; /* No login required if from 127.0.0.1 */
166 int noPswd; /* Logged in without password (on 127.0.0.1) */
167 int userUid; /* Integer user id */
@@ -168,11 +168,11 @@
168
169 /* Information used to populate the RCVFROM table */
170 int rcvid; /* The rcvid. 0 if not yet defined. */
171 char *zIpAddr; /* The remote IP address */
172 char *zNonce; /* The nonce used for login */
173
174 /* permissions used by the server */
175 struct FossilUserPerms perm;
176
177 #ifdef FOSSIL_ENABLE_TCL
178 /* all Tcl related context necessary for integration */
@@ -195,11 +195,11 @@
195 const char *azAuxName[MX_AUX]; /* Name of each aux() or option() value */
196 char *azAuxParam[MX_AUX]; /* Param of each aux() or option() value */
197 const char *azAuxVal[MX_AUX]; /* Value of each aux() or option() value */
198 const char **azAuxOpt[MX_AUX]; /* Options of each option() value */
199 int anAuxCols[MX_AUX]; /* Number of columns for option() values */
200
201 int allowSymlinks; /* Cached "allow-symlinks" option */
202
203 #ifdef FOSSIL_ENABLE_JSON
204 struct FossilJsonBits {
205 int isJsonMode; /* True if running in JSON mode, else
@@ -262,11 +262,11 @@
262 #endif
263
264 Global g;
265
266 /*
267 ** The table of web pages supported by this application is generated
268 ** automatically by the "mkindex" program and written into a file
269 ** named "page_index.h". We include that file here to get access
270 ** to the table.
271 */
272 #include "page_index.h"
@@ -329,30 +329,147 @@
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
460 ** (c) If the line begins with "-" and contains a space, it is broken
461 ** into two arguments at the space.
462 */
463 static void expand_args_option(int argc, void *argv){
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,13 +476,18 @@
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
487 for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
488 #endif
489 #endif
490 for(i=1; i<g.argc-1; i++){
491 z = g.argv[i];
492 if( z[0]!='-' ) continue;
493 z++;
@@ -390,21 +512,21 @@
512 }
513 z = blob_str(&file);
514 for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
515 newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
516 for(j=0; j<i; j++) newArgv[j] = g.argv[j];
517
518 blob_rewind(&file);
519 while( (n = blob_line(&file, &line))>0 ){
520 if( n<=1 ) continue;
521 z = blob_buffer(&line);
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;
@@ -430,11 +552,16 @@
552 }
553
554 /*
555 ** This procedure runs first.
556 */
557 #if defined(_WIN32) && defined(UNICODE)
558 int wmain(int argc, wchar_t **argv)
559 #else
560 int main(int argc, char **argv)
561 #endif
562 {
563 const char *zCmdName = "unknown";
564 int idx;
565 int rc;
566
567 sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
@@ -726,12 +853,12 @@
853 #else
854 /* On unix, evaluate the command directly.
855 */
856 if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
857 rc = system(zOrigCmd);
858 #endif
859 return rc;
860 }
861
862 /*
863 ** Turn off any NL to CRNL translation on the stream given as an
864 ** argument. This is a no-op on unix but is necessary on windows.
@@ -1194,11 +1321,11 @@
1321 ** * Environment variables are set up according to the CGI standard.
1322 **
1323 ** If the repository is known, it has already been opened. If unknown,
1324 ** then g.zRepositoryName holds the directory that contains the repository
1325 ** and the actual repository is taken from the first element of PATH_INFO.
1326 **
1327 ** Process the webpage specified by the PATH_INFO or REQUEST_URI
1328 ** environment variable.
1329 */
1330 static void process_one_web_page(const char *zNotFound){
1331 const char *zPathInfo;
@@ -1267,11 +1394,11 @@
1394 cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
1395 zPathInfo += i;
1396 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1397 db_open_repository(zRepo);
1398 if( g.fHttpTrace ){
1399 fprintf(stderr,
1400 "# repository: [%s]\n"
1401 "# new PATH_INFO = [%s]\n"
1402 "# new SCRIPT_NAME = [%s]\n",
1403 zRepo, zPathInfo, zNewScript);
1404 }
@@ -1282,11 +1409,11 @@
1409 */
1410 if( g.zContentType && memcmp(g.zContentType, "application/x-fossil", 20)==0 ){
1411 zPathInfo = "/xfer";
1412 }
1413 set_base_url();
1414 if( zPathInfo==0 || zPathInfo[0]==0
1415 || (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
1416 #ifdef FOSSIL_ENABLE_JSON
1417 if(g.json.isJsonMode){
1418 json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
1419 fossil_exit(0);
@@ -1312,11 +1439,11 @@
1439 ** that accepts the login credentials of the current repository. A
1440 ** subrepository is identified by a CONFIG table entry "subrepo:NAME"
1441 ** where NAME is the first component of the path. The value of the
1442 ** the CONFIG entries is the string "USER:FILENAME" where USER is the
1443 ** USER name to log in as in the subrepository and FILENAME is the
1444 ** repository filename.
1445 */
1446 zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
1447 g.zPath);
1448 if( zAltRepo ){
1449 int nHost;
@@ -1514,11 +1641,11 @@
1641
1642 /* If the CGI program contains one or more lines of the form
1643 **
1644 ** redirect: repository-filename http://hostname/path/%s
1645 **
1646 ** then control jumps here. Search each repository for an artifact ID
1647 ** that matches the "name" CGI parameter and for the first match,
1648 ** redirect to the corresponding URL with the "name" CGI parameter
1649 ** inserted. Paint an error page if no match is found.
1650 **
1651 ** If there is a line of the form:
@@ -1530,11 +1657,11 @@
1657 */
1658 void redirect_web_page(int nRedirect, char **azRedirect){
1659 int i; /* Loop counter */
1660 const char *zNotFound = 0; /* Not found URL */
1661 const char *zName = P("name");
1662 set_base_url();
1663 if( zName==0 ){
1664 zName = P("SCRIPT_NAME");
1665 if( zName && zName[0]=='/' ) zName++;
1666 }
1667 if( zName && validate16(zName, strlen(zName)) ){
@@ -1603,11 +1730,11 @@
1730 **
1731 ** Usage: %fossil http REPOSITORY ?OPTIONS?
1732 **
1733 ** Handle a single HTTP request appearing on stdin. The resulting webpage
1734 ** is delivered on stdout. This method is used to launch an HTTP request
1735 ** handler from inetd, for example. The argument is the name of the
1736 ** repository.
1737 **
1738 ** If REPOSITORY is a directory that contains one or more repositories
1739 ** with names of the form "*.fossil" then the first element of the URL
1740 ** pathname selects among the various repositories. If the pathname does
@@ -1742,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
@@ -1779,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/makemake.tcl
+++ src/makemake.tcl
@@ -473,10 +473,15 @@
473473
# With JSON support
474474
ifdef FOSSIL_ENABLE_JSON
475475
TCC += -DFOSSIL_ENABLE_JSON=1
476476
RCC += -DFOSSIL_ENABLE_JSON=1
477477
endif
478
+
479
+# Fix buggy MinGW command line parsing
480
+ifdef MINGW_BROKEN_MAINARGS
481
+TCC += -DMINGW_BROKEN_MAINARGS
482
+endif
478483
479484
#### We add the -static option here so that we can build a static
480485
# executable that will run in a chroot jail.
481486
#
482487
LIB = -static
483488
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -473,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 #### We add the -static option here so that we can build a static
480 # executable that will run in a chroot jail.
481 #
482 LIB = -static
483
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -473,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
+9 -18
--- src/printf.c
+++ src/printf.c
@@ -243,11 +243,11 @@
243243
blob_append(pBlob,"%",1);
244244
count++;
245245
break;
246246
}
247247
/* Find out what flags are present */
248
- flag_leftjustify = flag_plussign = flag_blanksign =
248
+ flag_leftjustify = flag_plussign = flag_blanksign =
249249
flag_alternateform = flag_altform2 = flag_zeropad = 0;
250250
done = 0;
251251
do{
252252
switch( c ){
253253
case '-': flag_leftjustify = 1; break;
@@ -814,25 +814,16 @@
814814
** if the output is going to the screen. If output is redirected into
815815
** a file, no translation occurs. No translation ever occurs on unix.
816816
*/
817817
void fossil_puts(const char *z, int toStdErr){
818818
#if defined(_WIN32)
819
- static int once = 1;
820
- static int istty[2];
821
- char *zToFree = 0;
822
- if( once ){
823
- istty[0] = _isatty(fileno(stdout));
824
- istty[1] = _isatty(fileno(stderr));
825
- once = 0;
826
- }
827
- assert( toStdErr==0 || toStdErr==1 );
828
- if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
829
- fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
830
- free(zToFree);
831
-#else
832
- fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
833
-#endif
819
+ if( fossil_utf8_to_console(z, strlen(z), toStdErr) >= 0 ){
820
+ return;
821
+ }
822
+#endif
823
+ assert( toStdErr==0 || toStdErr==1 );
824
+ fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
834825
fflush(toStdErr ? stderr : stdout);
835826
}
836827
837828
/*
838829
** Write output for user consumption. If g.cgiOutput is enabled, then
@@ -863,11 +854,11 @@
863854
return -1;
864855
}else if( zB==0 ){
865856
return +1;
866857
}else{
867858
int a, b;
868
- do{
859
+ do{
869860
a = *zA++;
870861
b = *zB++;
871862
}while( a==b && a!=0 );
872863
return ((unsigned char)a) - (unsigned char)b;
873864
}
@@ -878,11 +869,11 @@
878869
return -1;
879870
}else if( zB==0 ){
880871
return +1;
881872
}else if( nByte>0 ){
882873
int a, b;
883
- do{
874
+ do{
884875
a = *zA++;
885876
b = *zB++;
886877
}while( a==b && a!=0 && (--nByte)>0 );
887878
return ((unsigned char)a) - (unsigned char)b;
888879
}else{
889880
--- src/printf.c
+++ src/printf.c
@@ -243,11 +243,11 @@
243 blob_append(pBlob,"%",1);
244 count++;
245 break;
246 }
247 /* Find out what flags are present */
248 flag_leftjustify = flag_plussign = flag_blanksign =
249 flag_alternateform = flag_altform2 = flag_zeropad = 0;
250 done = 0;
251 do{
252 switch( c ){
253 case '-': flag_leftjustify = 1; break;
@@ -814,25 +814,16 @@
814 ** if the output is going to the screen. If output is redirected into
815 ** a file, no translation occurs. No translation ever occurs on unix.
816 */
817 void fossil_puts(const char *z, int toStdErr){
818 #if defined(_WIN32)
819 static int once = 1;
820 static int istty[2];
821 char *zToFree = 0;
822 if( once ){
823 istty[0] = _isatty(fileno(stdout));
824 istty[1] = _isatty(fileno(stderr));
825 once = 0;
826 }
827 assert( toStdErr==0 || toStdErr==1 );
828 if( istty[toStdErr] ) z = zToFree = fossil_utf8_to_console(z);
829 fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
830 free(zToFree);
831 #else
832 fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
833 #endif
834 fflush(toStdErr ? stderr : stdout);
835 }
836
837 /*
838 ** Write output for user consumption. If g.cgiOutput is enabled, then
@@ -863,11 +854,11 @@
863 return -1;
864 }else if( zB==0 ){
865 return +1;
866 }else{
867 int a, b;
868 do{
869 a = *zA++;
870 b = *zB++;
871 }while( a==b && a!=0 );
872 return ((unsigned char)a) - (unsigned char)b;
873 }
@@ -878,11 +869,11 @@
878 return -1;
879 }else if( zB==0 ){
880 return +1;
881 }else if( nByte>0 ){
882 int a, b;
883 do{
884 a = *zA++;
885 b = *zB++;
886 }while( a==b && a!=0 && (--nByte)>0 );
887 return ((unsigned char)a) - (unsigned char)b;
888 }else{
889
--- src/printf.c
+++ src/printf.c
@@ -243,11 +243,11 @@
243 blob_append(pBlob,"%",1);
244 count++;
245 break;
246 }
247 /* Find out what flags are present */
248 flag_leftjustify = flag_plussign = flag_blanksign =
249 flag_alternateform = flag_altform2 = flag_zeropad = 0;
250 done = 0;
251 do{
252 switch( c ){
253 case '-': flag_leftjustify = 1; break;
@@ -814,25 +814,16 @@
814 ** if the output is going to the screen. If output is redirected into
815 ** a file, no translation occurs. No translation ever occurs on unix.
816 */
817 void fossil_puts(const char *z, int toStdErr){
818 #if defined(_WIN32)
819 if( fossil_utf8_to_console(z, strlen(z), toStdErr) >= 0 ){
820 return;
821 }
822 #endif
823 assert( toStdErr==0 || toStdErr==1 );
824 fwrite(z, 1, strlen(z), toStdErr ? stderr : stdout);
 
 
 
 
 
 
 
 
 
825 fflush(toStdErr ? stderr : stdout);
826 }
827
828 /*
829 ** Write output for user consumption. If g.cgiOutput is enabled, then
@@ -863,11 +854,11 @@
854 return -1;
855 }else if( zB==0 ){
856 return +1;
857 }else{
858 int a, b;
859 do{
860 a = *zA++;
861 b = *zB++;
862 }while( a==b && a!=0 );
863 return ((unsigned char)a) - (unsigned char)b;
864 }
@@ -878,11 +869,11 @@
869 return -1;
870 }else if( zB==0 ){
871 return +1;
872 }else if( nByte>0 ){
873 int a, b;
874 do{
875 a = *zA++;
876 b = *zB++;
877 }while( a==b && a!=0 && (--nByte)>0 );
878 return ((unsigned char)a) - (unsigned char)b;
879 }else{
880
+37 -30
--- src/winhttp.c
+++ src/winhttp.c
@@ -109,11 +109,11 @@
109109
wanted -= got;
110110
}
111111
fclose(out);
112112
out = 0;
113113
sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
114
- fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
114
+ fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
115115
inet_ntoa(p->addr.sin_addr), p->zOptions
116116
);
117117
fossil_system(zCmd);
118118
in = fossil_fopen(zReplyFName, "rb");
119119
if( in ){
@@ -129,10 +129,15 @@
129129
file_delete(zRequestFName);
130130
file_delete(zReplyFName);
131131
free(p);
132132
}
133133
134
+#if !defined(UNICODE)
135
+# define fossil_unicode_to_utf8 fossil_mbcs_to_utf8
136
+# define fossil_utf8_to_unicode fossil_utf8_to_mbcs
137
+#endif
138
+
134139
/*
135140
** Start a listening socket and process incoming HTTP requests on
136141
** that socket.
137142
*/
138143
void win32_http_server(
@@ -146,11 +151,11 @@
146151
SOCKET s = INVALID_SOCKET;
147152
SOCKADDR_IN addr;
148153
int idCnt = 0;
149154
int iPort = mnPort;
150155
Blob options;
151
- char zTmpPath[MAX_PATH];
156
+ TCHAR zTmpPath[MAX_PATH];
152157
153158
if( zStopper ) file_delete(zStopper);
154159
blob_zero(&options);
155160
if( zNotFound ){
156161
blob_appendf(&options, " --notfound %s", zNotFound);
@@ -194,11 +199,11 @@
194199
}
195200
}
196201
if( !GetTempPath(MAX_PATH, zTmpPath) ){
197202
fossil_fatal("unable to get path to the temporary directory.");
198203
}
199
- zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_mbcs_to_utf8(zTmpPath), iPort);
204
+ zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort);
200205
fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
201206
if( zBrowser ){
202207
zBrowser = mprintf(zBrowser, iPort);
203208
fossil_print("Launch webbrowser: %s\n", zBrowser);
204209
fossil_system(zBrowser);
@@ -214,11 +219,11 @@
214219
int len = sizeof(client_addr);
215220
int wsaError;
216221
217222
client = accept(s, (struct sockaddr*)&client_addr, &len);
218223
if( client==INVALID_SOCKET ){
219
- /* If the service control handler has closed the listener socket,
224
+ /* If the service control handler has closed the listener socket,
220225
** cleanup and return, otherwise report a fatal error. */
221226
wsaError = WSAGetLastError();
222227
if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
223228
WSACleanup();
224229
return;
@@ -249,11 +254,11 @@
249254
struct HttpService {
250255
int port; /* Port on which the http server should run */
251256
const char *zNotFound; /* The --notfound option, or NULL */
252257
int flags; /* One or more HTTP_SERVER_ flags */
253258
int isRunningAsService; /* Are we running as a service ? */
254
- const char *zServiceName; /* Name of the service */
259
+ const TCHAR *zServiceName;/* Name of the service */
255260
SOCKET s; /* Socket on which the http server listens */
256261
};
257262
258263
/*
259264
** Variables used for running as windows service.
@@ -298,11 +303,11 @@
298303
0,
299304
NULL
300305
);
301306
}
302307
if( nMsg ){
303
- zMsg = fossil_mbcs_to_utf8(tmp);
308
+ zMsg = fossil_unicode_to_utf8(tmp);
304309
}else{
305310
fossil_fatal("unable to get system error message.");
306311
}
307312
if( tmp ){
308313
LocalFree((HLOCAL) tmp);
@@ -326,11 +331,11 @@
326331
}
327332
ssStatus.dwCurrentState = dwCurrentState;
328333
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
329334
ssStatus.dwWaitHint = dwWaitHint;
330335
331
- if( (dwCurrentState==SERVICE_RUNNING) ||
336
+ if( (dwCurrentState==SERVICE_RUNNING) ||
332337
(dwCurrentState==SERVICE_STOPPED) ){
333338
ssStatus.dwCheckPoint = 0;
334339
}else{
335340
ssStatus.dwCheckPoint++;
336341
}
@@ -384,11 +389,11 @@
384389
if( argc>0 ){
385390
hsData.zServiceName = argv[0];
386391
}
387392
388393
/* Register the service control handler function */
389
- sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl);
394
+ sshStatusHandle = RegisterServiceCtrlHandler(TEXT(""), win32_http_service_ctrl);
390395
if( !sshStatusHandle ){
391396
win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
392397
return;
393398
}
394399
@@ -429,12 +434,12 @@
429434
const char *zNotFound, /* The --notfound option, or NULL */
430435
int flags /* One or more HTTP_SERVER_ flags */
431436
){
432437
/* Define the service table. */
433438
SERVICE_TABLE_ENTRY ServiceTable[] =
434
- {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
435
-
439
+ {{TEXT(""), (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
440
+
436441
/* Initialize the HttpService structure. */
437442
hsData.port = nPort;
438443
hsData.zNotFound = zNotFound;
439444
hsData.flags = flags;
440445
@@ -447,11 +452,12 @@
447452
}
448453
}
449454
return 0;
450455
}
451456
452
-/*
457
+#ifdef _WIN32
458
+/* dupe ifdef needed for mkindex
453459
** COMMAND: winsrv*
454460
** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
455461
**
456462
** Where METHOD is one of: create delete show start stop.
457463
**
@@ -459,11 +465,11 @@
459465
** (for example) Fossil to be running in the background when no user
460466
** is logged in.
461467
**
462468
** In the following description of the methods, "Fossil-DSCM" will be
463469
** used as the default SERVICE-NAME:
464
-**
470
+**
465471
** fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
466472
**
467473
** Creates a service. Available options include:
468474
**
469475
** -D|--display DISPLAY-NAME
@@ -565,11 +571,11 @@
565571
566572
if( strncmp(zMethod, "create", n)==0 ){
567573
SC_HANDLE hScm;
568574
SC_HANDLE hSvc;
569575
SERVICE_DESCRIPTION
570
- svcDescr = {"Fossil - Distributed Software Configuration Management"};
576
+ svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")};
571577
char *zErrFmt = "unable to create service '%s': %s";
572578
DWORD dwStartType = SERVICE_DEMAND_START;
573579
const char *zDisplay = find_option("display", "D", 1);
574580
const char *zStart = find_option("start", "S", 1);
575581
const char *zUsername = find_option("username", "U", 1);
@@ -624,22 +630,22 @@
624630
/* Create the service. */
625631
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
626632
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
627633
hSvc = CreateService(
628634
hScm, /* Handle to the SCM */
629
- fossil_utf8_to_mbcs(zSvcName), /* Name of the service */
630
- fossil_utf8_to_mbcs(zDisplay), /* Display name */
635
+ fossil_utf8_to_unicode(zSvcName), /* Name of the service */
636
+ fossil_utf8_to_unicode(zDisplay), /* Display name */
631637
SERVICE_ALL_ACCESS, /* Desired access */
632638
SERVICE_WIN32_OWN_PROCESS, /* Service type */
633639
dwStartType, /* Start type */
634640
SERVICE_ERROR_NORMAL, /* Error control */
635
- fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */
641
+ fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
636642
NULL, /* Load ordering group */
637643
NULL, /* Tag value */
638644
NULL, /* Service dependencies */
639
- fossil_utf8_to_mbcs(zUsername), /* Service account */
640
- fossil_utf8_to_mbcs(zPassword) /* Account password */
645
+ fossil_utf8_to_unicode(zUsername), /* Service account */
646
+ fossil_utf8_to_unicode(zPassword) /* Account password */
641647
);
642648
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
643649
/* Set the service description. */
644650
ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
645651
fossil_print("Service '%s' successfully created.\n", zSvcName);
@@ -658,11 +664,11 @@
658664
}else if( g.argc>4 ){
659665
fossil_fatal("to much arguments for delete method.");
660666
}
661667
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
662668
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
663
- hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
669
+ hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
664670
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
665671
QueryServiceStatus(hSvc, &sstat);
666672
if( sstat.dwCurrentState!=SERVICE_STOPPED ){
667673
fossil_print("Stopping service '%s'", zSvcName);
668674
if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -695,28 +701,28 @@
695701
SERVICE_STATUS sstat;
696702
LPQUERY_SERVICE_CONFIG pSvcConfig;
697703
LPSERVICE_DESCRIPTION pSvcDescr;
698704
BOOL bStatus;
699705
DWORD nRequired;
700
- char *zErrFmt = "unable to show service '%s': %s";
701
- static const char *zSvcTypes[] = {
706
+ const char *zErrFmt = "unable to show service '%s': %s";
707
+ static const char *const zSvcTypes[] = {
702708
"Driver service",
703709
"File system driver service",
704710
"Service runs in its own process",
705711
"Service shares a process with other services",
706712
"Service can interact with the desktop"
707713
};
708714
const char *zSvcType = "";
709
- static char *zSvcStartTypes[] = {
715
+ static const char *const zSvcStartTypes[] = {
710716
"Started by the system loader",
711717
"Started by the IoInitSystem function",
712718
"Started automatically by the service control manager",
713719
"Started manually",
714720
"Service cannot be started"
715721
};
716722
const char *zSvcStartType = "";
717
- static const char *zSvcStates[] = {
723
+ static const char *const zSvcStates[] = {
718724
"Stopped", "Starting", "Stopping", "Running",
719725
"Continue pending", "Pause pending", "Paused"
720726
};
721727
const char *zSvcState = "";
722728
@@ -726,11 +732,11 @@
726732
}else if( g.argc>4 ){
727733
fossil_fatal("to much arguments for show method.");
728734
}
729735
hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
730736
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
731
- hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ);
737
+ hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
732738
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
733739
/* Get the service configuration */
734740
bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired);
735741
if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
736742
fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -778,19 +784,19 @@
778784
case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break;
779785
}
780786
/* Print service information to terminal */
781787
fossil_print("Service name .......: %s\n", zSvcName);
782788
fossil_print("Display name .......: %s\n",
783
- fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName));
789
+ fossil_unicode_to_utf8(pSvcConfig->lpDisplayName));
784790
fossil_print("Service description : %s\n",
785
- fossil_mbcs_to_utf8(pSvcDescr->lpDescription));
791
+ fossil_unicode_to_utf8(pSvcDescr->lpDescription));
786792
fossil_print("Service type .......: %s.\n", zSvcType);
787793
fossil_print("Service start type .: %s.\n", zSvcStartType);
788794
fossil_print("Binary path name ...: %s\n",
789
- fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName));
795
+ fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName));
790796
fossil_print("Service username ...: %s\n",
791
- fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName));
797
+ fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName));
792798
fossil_print("Current state ......: %s.\n", zSvcState);
793799
/* Cleanup */
794800
fossil_free(pSvcConfig);
795801
fossil_free(pSvcDescr);
796802
CloseServiceHandle(hSvc);
@@ -808,11 +814,11 @@
808814
}else if( g.argc>4 ){
809815
fossil_fatal("to much arguments for start method.");
810816
}
811817
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
812818
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
813
- hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
819
+ hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
814820
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
815821
QueryServiceStatus(hSvc, &sstat);
816822
if( sstat.dwCurrentState!=SERVICE_RUNNING ){
817823
fossil_print("Starting service '%s'", zSvcName);
818824
if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
@@ -844,11 +850,11 @@
844850
}else if( g.argc>4 ){
845851
fossil_fatal("to much arguments for stop method.");
846852
}
847853
hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
848854
if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
849
- hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
855
+ hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
850856
if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
851857
QueryServiceStatus(hSvc, &sstat);
852858
if( sstat.dwCurrentState!=SERVICE_STOPPED ){
853859
fossil_print("Stopping service '%s'", zSvcName);
854860
if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -872,7 +878,8 @@
872878
fossil_fatal("METHOD should be one of:"
873879
" create delete show start stop");
874880
}
875881
return;
876882
}
883
+#endif /* _WIN32 */
877884
878885
#endif /* _WIN32 -- This code is for win32 only */
879886
880887
ADDED test/cmdline.test
--- src/winhttp.c
+++ src/winhttp.c
@@ -109,11 +109,11 @@
109 wanted -= got;
110 }
111 fclose(out);
112 out = 0;
113 sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
114 fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
115 inet_ntoa(p->addr.sin_addr), p->zOptions
116 );
117 fossil_system(zCmd);
118 in = fossil_fopen(zReplyFName, "rb");
119 if( in ){
@@ -129,10 +129,15 @@
129 file_delete(zRequestFName);
130 file_delete(zReplyFName);
131 free(p);
132 }
133
 
 
 
 
 
134 /*
135 ** Start a listening socket and process incoming HTTP requests on
136 ** that socket.
137 */
138 void win32_http_server(
@@ -146,11 +151,11 @@
146 SOCKET s = INVALID_SOCKET;
147 SOCKADDR_IN addr;
148 int idCnt = 0;
149 int iPort = mnPort;
150 Blob options;
151 char zTmpPath[MAX_PATH];
152
153 if( zStopper ) file_delete(zStopper);
154 blob_zero(&options);
155 if( zNotFound ){
156 blob_appendf(&options, " --notfound %s", zNotFound);
@@ -194,11 +199,11 @@
194 }
195 }
196 if( !GetTempPath(MAX_PATH, zTmpPath) ){
197 fossil_fatal("unable to get path to the temporary directory.");
198 }
199 zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_mbcs_to_utf8(zTmpPath), iPort);
200 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
201 if( zBrowser ){
202 zBrowser = mprintf(zBrowser, iPort);
203 fossil_print("Launch webbrowser: %s\n", zBrowser);
204 fossil_system(zBrowser);
@@ -214,11 +219,11 @@
214 int len = sizeof(client_addr);
215 int wsaError;
216
217 client = accept(s, (struct sockaddr*)&client_addr, &len);
218 if( client==INVALID_SOCKET ){
219 /* If the service control handler has closed the listener socket,
220 ** cleanup and return, otherwise report a fatal error. */
221 wsaError = WSAGetLastError();
222 if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
223 WSACleanup();
224 return;
@@ -249,11 +254,11 @@
249 struct HttpService {
250 int port; /* Port on which the http server should run */
251 const char *zNotFound; /* The --notfound option, or NULL */
252 int flags; /* One or more HTTP_SERVER_ flags */
253 int isRunningAsService; /* Are we running as a service ? */
254 const char *zServiceName; /* Name of the service */
255 SOCKET s; /* Socket on which the http server listens */
256 };
257
258 /*
259 ** Variables used for running as windows service.
@@ -298,11 +303,11 @@
298 0,
299 NULL
300 );
301 }
302 if( nMsg ){
303 zMsg = fossil_mbcs_to_utf8(tmp);
304 }else{
305 fossil_fatal("unable to get system error message.");
306 }
307 if( tmp ){
308 LocalFree((HLOCAL) tmp);
@@ -326,11 +331,11 @@
326 }
327 ssStatus.dwCurrentState = dwCurrentState;
328 ssStatus.dwWin32ExitCode = dwWin32ExitCode;
329 ssStatus.dwWaitHint = dwWaitHint;
330
331 if( (dwCurrentState==SERVICE_RUNNING) ||
332 (dwCurrentState==SERVICE_STOPPED) ){
333 ssStatus.dwCheckPoint = 0;
334 }else{
335 ssStatus.dwCheckPoint++;
336 }
@@ -384,11 +389,11 @@
384 if( argc>0 ){
385 hsData.zServiceName = argv[0];
386 }
387
388 /* Register the service control handler function */
389 sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl);
390 if( !sshStatusHandle ){
391 win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
392 return;
393 }
394
@@ -429,12 +434,12 @@
429 const char *zNotFound, /* The --notfound option, or NULL */
430 int flags /* One or more HTTP_SERVER_ flags */
431 ){
432 /* Define the service table. */
433 SERVICE_TABLE_ENTRY ServiceTable[] =
434 {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
435
436 /* Initialize the HttpService structure. */
437 hsData.port = nPort;
438 hsData.zNotFound = zNotFound;
439 hsData.flags = flags;
440
@@ -447,11 +452,12 @@
447 }
448 }
449 return 0;
450 }
451
452 /*
 
453 ** COMMAND: winsrv*
454 ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
455 **
456 ** Where METHOD is one of: create delete show start stop.
457 **
@@ -459,11 +465,11 @@
459 ** (for example) Fossil to be running in the background when no user
460 ** is logged in.
461 **
462 ** In the following description of the methods, "Fossil-DSCM" will be
463 ** used as the default SERVICE-NAME:
464 **
465 ** fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
466 **
467 ** Creates a service. Available options include:
468 **
469 ** -D|--display DISPLAY-NAME
@@ -565,11 +571,11 @@
565
566 if( strncmp(zMethod, "create", n)==0 ){
567 SC_HANDLE hScm;
568 SC_HANDLE hSvc;
569 SERVICE_DESCRIPTION
570 svcDescr = {"Fossil - Distributed Software Configuration Management"};
571 char *zErrFmt = "unable to create service '%s': %s";
572 DWORD dwStartType = SERVICE_DEMAND_START;
573 const char *zDisplay = find_option("display", "D", 1);
574 const char *zStart = find_option("start", "S", 1);
575 const char *zUsername = find_option("username", "U", 1);
@@ -624,22 +630,22 @@
624 /* Create the service. */
625 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
626 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
627 hSvc = CreateService(
628 hScm, /* Handle to the SCM */
629 fossil_utf8_to_mbcs(zSvcName), /* Name of the service */
630 fossil_utf8_to_mbcs(zDisplay), /* Display name */
631 SERVICE_ALL_ACCESS, /* Desired access */
632 SERVICE_WIN32_OWN_PROCESS, /* Service type */
633 dwStartType, /* Start type */
634 SERVICE_ERROR_NORMAL, /* Error control */
635 fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */
636 NULL, /* Load ordering group */
637 NULL, /* Tag value */
638 NULL, /* Service dependencies */
639 fossil_utf8_to_mbcs(zUsername), /* Service account */
640 fossil_utf8_to_mbcs(zPassword) /* Account password */
641 );
642 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
643 /* Set the service description. */
644 ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
645 fossil_print("Service '%s' successfully created.\n", zSvcName);
@@ -658,11 +664,11 @@
658 }else if( g.argc>4 ){
659 fossil_fatal("to much arguments for delete method.");
660 }
661 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
662 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
663 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
664 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
665 QueryServiceStatus(hSvc, &sstat);
666 if( sstat.dwCurrentState!=SERVICE_STOPPED ){
667 fossil_print("Stopping service '%s'", zSvcName);
668 if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -695,28 +701,28 @@
695 SERVICE_STATUS sstat;
696 LPQUERY_SERVICE_CONFIG pSvcConfig;
697 LPSERVICE_DESCRIPTION pSvcDescr;
698 BOOL bStatus;
699 DWORD nRequired;
700 char *zErrFmt = "unable to show service '%s': %s";
701 static const char *zSvcTypes[] = {
702 "Driver service",
703 "File system driver service",
704 "Service runs in its own process",
705 "Service shares a process with other services",
706 "Service can interact with the desktop"
707 };
708 const char *zSvcType = "";
709 static char *zSvcStartTypes[] = {
710 "Started by the system loader",
711 "Started by the IoInitSystem function",
712 "Started automatically by the service control manager",
713 "Started manually",
714 "Service cannot be started"
715 };
716 const char *zSvcStartType = "";
717 static const char *zSvcStates[] = {
718 "Stopped", "Starting", "Stopping", "Running",
719 "Continue pending", "Pause pending", "Paused"
720 };
721 const char *zSvcState = "";
722
@@ -726,11 +732,11 @@
726 }else if( g.argc>4 ){
727 fossil_fatal("to much arguments for show method.");
728 }
729 hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
730 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
731 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ);
732 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
733 /* Get the service configuration */
734 bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired);
735 if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
736 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -778,19 +784,19 @@
778 case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break;
779 }
780 /* Print service information to terminal */
781 fossil_print("Service name .......: %s\n", zSvcName);
782 fossil_print("Display name .......: %s\n",
783 fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName));
784 fossil_print("Service description : %s\n",
785 fossil_mbcs_to_utf8(pSvcDescr->lpDescription));
786 fossil_print("Service type .......: %s.\n", zSvcType);
787 fossil_print("Service start type .: %s.\n", zSvcStartType);
788 fossil_print("Binary path name ...: %s\n",
789 fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName));
790 fossil_print("Service username ...: %s\n",
791 fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName));
792 fossil_print("Current state ......: %s.\n", zSvcState);
793 /* Cleanup */
794 fossil_free(pSvcConfig);
795 fossil_free(pSvcDescr);
796 CloseServiceHandle(hSvc);
@@ -808,11 +814,11 @@
808 }else if( g.argc>4 ){
809 fossil_fatal("to much arguments for start method.");
810 }
811 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
812 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
813 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
814 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
815 QueryServiceStatus(hSvc, &sstat);
816 if( sstat.dwCurrentState!=SERVICE_RUNNING ){
817 fossil_print("Starting service '%s'", zSvcName);
818 if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
@@ -844,11 +850,11 @@
844 }else if( g.argc>4 ){
845 fossil_fatal("to much arguments for stop method.");
846 }
847 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
848 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
849 hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS);
850 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
851 QueryServiceStatus(hSvc, &sstat);
852 if( sstat.dwCurrentState!=SERVICE_STOPPED ){
853 fossil_print("Stopping service '%s'", zSvcName);
854 if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -872,7 +878,8 @@
872 fossil_fatal("METHOD should be one of:"
873 " create delete show start stop");
874 }
875 return;
876 }
 
877
878 #endif /* _WIN32 -- This code is for win32 only */
879
880 DDED test/cmdline.test
--- src/winhttp.c
+++ src/winhttp.c
@@ -109,11 +109,11 @@
109 wanted -= got;
110 }
111 fclose(out);
112 out = 0;
113 sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
114 fossil_nameofexe(), g.zRepositoryName, zRequestFName, zReplyFName,
115 inet_ntoa(p->addr.sin_addr), p->zOptions
116 );
117 fossil_system(zCmd);
118 in = fossil_fopen(zReplyFName, "rb");
119 if( in ){
@@ -129,10 +129,15 @@
129 file_delete(zRequestFName);
130 file_delete(zReplyFName);
131 free(p);
132 }
133
134 #if !defined(UNICODE)
135 # define fossil_unicode_to_utf8 fossil_mbcs_to_utf8
136 # define fossil_utf8_to_unicode fossil_utf8_to_mbcs
137 #endif
138
139 /*
140 ** Start a listening socket and process incoming HTTP requests on
141 ** that socket.
142 */
143 void win32_http_server(
@@ -146,11 +151,11 @@
151 SOCKET s = INVALID_SOCKET;
152 SOCKADDR_IN addr;
153 int idCnt = 0;
154 int iPort = mnPort;
155 Blob options;
156 TCHAR zTmpPath[MAX_PATH];
157
158 if( zStopper ) file_delete(zStopper);
159 blob_zero(&options);
160 if( zNotFound ){
161 blob_appendf(&options, " --notfound %s", zNotFound);
@@ -194,11 +199,11 @@
199 }
200 }
201 if( !GetTempPath(MAX_PATH, zTmpPath) ){
202 fossil_fatal("unable to get path to the temporary directory.");
203 }
204 zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort);
205 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
206 if( zBrowser ){
207 zBrowser = mprintf(zBrowser, iPort);
208 fossil_print("Launch webbrowser: %s\n", zBrowser);
209 fossil_system(zBrowser);
@@ -214,11 +219,11 @@
219 int len = sizeof(client_addr);
220 int wsaError;
221
222 client = accept(s, (struct sockaddr*)&client_addr, &len);
223 if( client==INVALID_SOCKET ){
224 /* If the service control handler has closed the listener socket,
225 ** cleanup and return, otherwise report a fatal error. */
226 wsaError = WSAGetLastError();
227 if( (wsaError==WSAEINTR) || (wsaError==WSAENOTSOCK) ){
228 WSACleanup();
229 return;
@@ -249,11 +254,11 @@
254 struct HttpService {
255 int port; /* Port on which the http server should run */
256 const char *zNotFound; /* The --notfound option, or NULL */
257 int flags; /* One or more HTTP_SERVER_ flags */
258 int isRunningAsService; /* Are we running as a service ? */
259 const TCHAR *zServiceName;/* Name of the service */
260 SOCKET s; /* Socket on which the http server listens */
261 };
262
263 /*
264 ** Variables used for running as windows service.
@@ -298,11 +303,11 @@
303 0,
304 NULL
305 );
306 }
307 if( nMsg ){
308 zMsg = fossil_unicode_to_utf8(tmp);
309 }else{
310 fossil_fatal("unable to get system error message.");
311 }
312 if( tmp ){
313 LocalFree((HLOCAL) tmp);
@@ -326,11 +331,11 @@
331 }
332 ssStatus.dwCurrentState = dwCurrentState;
333 ssStatus.dwWin32ExitCode = dwWin32ExitCode;
334 ssStatus.dwWaitHint = dwWaitHint;
335
336 if( (dwCurrentState==SERVICE_RUNNING) ||
337 (dwCurrentState==SERVICE_STOPPED) ){
338 ssStatus.dwCheckPoint = 0;
339 }else{
340 ssStatus.dwCheckPoint++;
341 }
@@ -384,11 +389,11 @@
389 if( argc>0 ){
390 hsData.zServiceName = argv[0];
391 }
392
393 /* Register the service control handler function */
394 sshStatusHandle = RegisterServiceCtrlHandler(TEXT(""), win32_http_service_ctrl);
395 if( !sshStatusHandle ){
396 win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
397 return;
398 }
399
@@ -429,12 +434,12 @@
434 const char *zNotFound, /* The --notfound option, or NULL */
435 int flags /* One or more HTTP_SERVER_ flags */
436 ){
437 /* Define the service table. */
438 SERVICE_TABLE_ENTRY ServiceTable[] =
439 {{TEXT(""), (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}};
440
441 /* Initialize the HttpService structure. */
442 hsData.port = nPort;
443 hsData.zNotFound = zNotFound;
444 hsData.flags = flags;
445
@@ -447,11 +452,12 @@
452 }
453 }
454 return 0;
455 }
456
457 #ifdef _WIN32
458 /* dupe ifdef needed for mkindex
459 ** COMMAND: winsrv*
460 ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
461 **
462 ** Where METHOD is one of: create delete show start stop.
463 **
@@ -459,11 +465,11 @@
465 ** (for example) Fossil to be running in the background when no user
466 ** is logged in.
467 **
468 ** In the following description of the methods, "Fossil-DSCM" will be
469 ** used as the default SERVICE-NAME:
470 **
471 ** fossil winsrv create ?SERVICE-NAME? ?OPTIONS?
472 **
473 ** Creates a service. Available options include:
474 **
475 ** -D|--display DISPLAY-NAME
@@ -565,11 +571,11 @@
571
572 if( strncmp(zMethod, "create", n)==0 ){
573 SC_HANDLE hScm;
574 SC_HANDLE hSvc;
575 SERVICE_DESCRIPTION
576 svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")};
577 char *zErrFmt = "unable to create service '%s': %s";
578 DWORD dwStartType = SERVICE_DEMAND_START;
579 const char *zDisplay = find_option("display", "D", 1);
580 const char *zStart = find_option("start", "S", 1);
581 const char *zUsername = find_option("username", "U", 1);
@@ -624,22 +630,22 @@
630 /* Create the service. */
631 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
632 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
633 hSvc = CreateService(
634 hScm, /* Handle to the SCM */
635 fossil_utf8_to_unicode(zSvcName), /* Name of the service */
636 fossil_utf8_to_unicode(zDisplay), /* Display name */
637 SERVICE_ALL_ACCESS, /* Desired access */
638 SERVICE_WIN32_OWN_PROCESS, /* Service type */
639 dwStartType, /* Start type */
640 SERVICE_ERROR_NORMAL, /* Error control */
641 fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */
642 NULL, /* Load ordering group */
643 NULL, /* Tag value */
644 NULL, /* Service dependencies */
645 fossil_utf8_to_unicode(zUsername), /* Service account */
646 fossil_utf8_to_unicode(zPassword) /* Account password */
647 );
648 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
649 /* Set the service description. */
650 ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr);
651 fossil_print("Service '%s' successfully created.\n", zSvcName);
@@ -658,11 +664,11 @@
664 }else if( g.argc>4 ){
665 fossil_fatal("to much arguments for delete method.");
666 }
667 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
668 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
669 hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
670 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
671 QueryServiceStatus(hSvc, &sstat);
672 if( sstat.dwCurrentState!=SERVICE_STOPPED ){
673 fossil_print("Stopping service '%s'", zSvcName);
674 if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -695,28 +701,28 @@
701 SERVICE_STATUS sstat;
702 LPQUERY_SERVICE_CONFIG pSvcConfig;
703 LPSERVICE_DESCRIPTION pSvcDescr;
704 BOOL bStatus;
705 DWORD nRequired;
706 const char *zErrFmt = "unable to show service '%s': %s";
707 static const char *const zSvcTypes[] = {
708 "Driver service",
709 "File system driver service",
710 "Service runs in its own process",
711 "Service shares a process with other services",
712 "Service can interact with the desktop"
713 };
714 const char *zSvcType = "";
715 static const char *const zSvcStartTypes[] = {
716 "Started by the system loader",
717 "Started by the IoInitSystem function",
718 "Started automatically by the service control manager",
719 "Started manually",
720 "Service cannot be started"
721 };
722 const char *zSvcStartType = "";
723 static const char *const zSvcStates[] = {
724 "Stopped", "Starting", "Stopping", "Running",
725 "Continue pending", "Pause pending", "Paused"
726 };
727 const char *zSvcState = "";
728
@@ -726,11 +732,11 @@
732 }else if( g.argc>4 ){
733 fossil_fatal("to much arguments for show method.");
734 }
735 hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
736 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
737 hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ);
738 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
739 /* Get the service configuration */
740 bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired);
741 if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
742 fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
@@ -778,19 +784,19 @@
784 case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break;
785 }
786 /* Print service information to terminal */
787 fossil_print("Service name .......: %s\n", zSvcName);
788 fossil_print("Display name .......: %s\n",
789 fossil_unicode_to_utf8(pSvcConfig->lpDisplayName));
790 fossil_print("Service description : %s\n",
791 fossil_unicode_to_utf8(pSvcDescr->lpDescription));
792 fossil_print("Service type .......: %s.\n", zSvcType);
793 fossil_print("Service start type .: %s.\n", zSvcStartType);
794 fossil_print("Binary path name ...: %s\n",
795 fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName));
796 fossil_print("Service username ...: %s\n",
797 fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName));
798 fossil_print("Current state ......: %s.\n", zSvcState);
799 /* Cleanup */
800 fossil_free(pSvcConfig);
801 fossil_free(pSvcDescr);
802 CloseServiceHandle(hSvc);
@@ -808,11 +814,11 @@
814 }else if( g.argc>4 ){
815 fossil_fatal("to much arguments for start method.");
816 }
817 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
818 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
819 hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
820 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
821 QueryServiceStatus(hSvc, &sstat);
822 if( sstat.dwCurrentState!=SERVICE_RUNNING ){
823 fossil_print("Starting service '%s'", zSvcName);
824 if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
@@ -844,11 +850,11 @@
850 }else if( g.argc>4 ){
851 fossil_fatal("to much arguments for stop method.");
852 }
853 hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
854 if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
855 hSvc = OpenService(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS);
856 if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg());
857 QueryServiceStatus(hSvc, &sstat);
858 if( sstat.dwCurrentState!=SERVICE_STOPPED ){
859 fossil_print("Stopping service '%s'", zSvcName);
860 if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){
@@ -872,7 +878,8 @@
878 fossil_fatal("METHOD should be one of:"
879 " create delete show start stop");
880 }
881 return;
882 }
883 #endif /* _WIN32 */
884
885 #endif /* _WIN32 -- This code is for win32 only */
886
887 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
--- 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.msc
+++ win/Makefile.msc
@@ -32,11 +32,11 @@
3232
ZLIBDIR = $(MSCDIR)\extra\lib
3333
ZLIB = zlib.lib
3434
3535
INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
3636
37
-CFLAGS = -nologo -MT -O2
37
+CFLAGS = -nologo -MT -O2 -DUNICODE -D_UNICODE
3838
BCC = $(CC) $(CFLAGS)
3939
TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
4040
LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
4141
LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
4242
4343
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -32,11 +32,11 @@
32 ZLIBDIR = $(MSCDIR)\extra\lib
33 ZLIB = zlib.lib
34
35 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
36
37 CFLAGS = -nologo -MT -O2
38 BCC = $(CC) $(CFLAGS)
39 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
40 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
41 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
42
43
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -32,11 +32,11 @@
32 ZLIBDIR = $(MSCDIR)\extra\lib
33 ZLIB = zlib.lib
34
35 INCL = -I. -I$(SRCDIR) -I$B\win\include -I$(MSCDIR)\extra\include -I$(ZINCDIR)
36
37 CFLAGS = -nologo -MT -O2 -DUNICODE -D_UNICODE
38 BCC = $(CC) $(CFLAGS)
39 TCC = $(CC) -c $(CFLAGS) $(MSCDEF) $(SSL) $(INCL)
40 LIBS = $(ZLIB) ws2_32.lib advapi32.lib $(SSLLIB)
41 LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
42
43

Keyboard Shortcuts

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