Fossil SCM

Add the --errorlog command-line option and the errorlog: parameter to CGI scripts. Log all panics, fatal errors, and warnings to the error log, if defined. Panic if file descriptor 2 is not open on unix. Clean up some routines that deal with close().

drh 2013-08-30 12:18 UTC trunk
Commit 4727ef4a8e6b266b9f6bb7f327b078fbe5b8d4fe
+14 -15
--- src/blob.c
+++ src/blob.c
@@ -766,21 +766,20 @@
766766
**
767767
** Return the number of bytes written.
768768
*/
769769
int blob_write_to_file(Blob *pBlob, const char *zFilename){
770770
FILE *out;
771
- int wrote;
771
+ int nWrote;
772772
773773
if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
774
- int n = blob_size(pBlob);
774
+ nWrote = blob_size(pBlob);
775775
#if defined(_WIN32)
776
- if( fossil_utf8_to_console(blob_buffer(pBlob), n, 0) >= 0 ){
777
- return n;
776
+ if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){
777
+ return nWrote;
778778
}
779779
#endif
780
- fwrite(blob_buffer(pBlob), 1, n, stdout);
781
- return n;
780
+ fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
782781
}else{
783782
int i, nName;
784783
char *zName, zBuf[1000];
785784
786785
nName = strlen(zFilename);
@@ -816,19 +815,19 @@
816815
if( out==0 ){
817816
fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
818817
return 0;
819818
}
820819
if( zName!=zBuf ) free(zName);
821
- }
822
- blob_is_init(pBlob);
823
- wrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
824
- fclose(out);
825
- if( wrote!=blob_size(pBlob) && out!=stdout ){
826
- fossil_fatal_recursive("short write: %d of %d bytes to %s", wrote,
827
- blob_size(pBlob), zFilename);
828
- }
829
- return wrote;
820
+ blob_is_init(pBlob);
821
+ nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
822
+ fclose(out);
823
+ if( nWrote!=blob_size(pBlob) ){
824
+ fossil_fatal_recursive("short write: %d of %d bytes to %s", nWrote,
825
+ blob_size(pBlob), zFilename);
826
+ }
827
+ }
828
+ return nWrote;
830829
}
831830
832831
/*
833832
** Compress a blob pIn. Store the result in pOut. It is ok for pIn and
834833
** pOut to be the same blob.
835834
--- src/blob.c
+++ src/blob.c
@@ -766,21 +766,20 @@
766 **
767 ** Return the number of bytes written.
768 */
769 int blob_write_to_file(Blob *pBlob, const char *zFilename){
770 FILE *out;
771 int wrote;
772
773 if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
774 int n = blob_size(pBlob);
775 #if defined(_WIN32)
776 if( fossil_utf8_to_console(blob_buffer(pBlob), n, 0) >= 0 ){
777 return n;
778 }
779 #endif
780 fwrite(blob_buffer(pBlob), 1, n, stdout);
781 return n;
782 }else{
783 int i, nName;
784 char *zName, zBuf[1000];
785
786 nName = strlen(zFilename);
@@ -816,19 +815,19 @@
816 if( out==0 ){
817 fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
818 return 0;
819 }
820 if( zName!=zBuf ) free(zName);
821 }
822 blob_is_init(pBlob);
823 wrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
824 fclose(out);
825 if( wrote!=blob_size(pBlob) && out!=stdout ){
826 fossil_fatal_recursive("short write: %d of %d bytes to %s", wrote,
827 blob_size(pBlob), zFilename);
828 }
829 return wrote;
830 }
831
832 /*
833 ** Compress a blob pIn. Store the result in pOut. It is ok for pIn and
834 ** pOut to be the same blob.
835
--- src/blob.c
+++ src/blob.c
@@ -766,21 +766,20 @@
766 **
767 ** Return the number of bytes written.
768 */
769 int blob_write_to_file(Blob *pBlob, const char *zFilename){
770 FILE *out;
771 int nWrote;
772
773 if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
774 nWrote = blob_size(pBlob);
775 #if defined(_WIN32)
776 if( fossil_utf8_to_console(blob_buffer(pBlob), nWrote, 0) >= 0 ){
777 return nWrote;
778 }
779 #endif
780 fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
 
781 }else{
782 int i, nName;
783 char *zName, zBuf[1000];
784
785 nName = strlen(zFilename);
@@ -816,19 +815,19 @@
815 if( out==0 ){
816 fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
817 return 0;
818 }
819 if( zName!=zBuf ) free(zName);
820 blob_is_init(pBlob);
821 nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
822 fclose(out);
823 if( nWrote!=blob_size(pBlob) ){
824 fossil_fatal_recursive("short write: %d of %d bytes to %s", nWrote,
825 blob_size(pBlob), zFilename);
826 }
827 }
828 return nWrote;
829 }
830
831 /*
832 ** Compress a blob pIn. Store the result in pOut. It is ok for pIn and
833 ** pOut to be the same blob.
834
+14 -7
--- src/main.c
+++ src/main.c
@@ -114,10 +114,11 @@
114114
** All global variables are in this structure.
115115
*/
116116
struct Global {
117117
int argc; char **argv; /* Command-line arguments to the program */
118118
char *nameOfExe; /* Full path of executable. */
119
+ const char *zErrlog; /* Log errors to this file, if not NULL */
119120
int isConst; /* True if the output is unchanging */
120121
sqlite3 *db; /* The connection to the databases */
121122
sqlite3 *dbConfig; /* Separate connection for global_config table */
122123
int useAttach; /* True if global_config is attached to repository */
123124
const char *zConfigDbName;/* Path of the config database. NULL if not open */
@@ -372,11 +373,11 @@
372373
unsigned int i, j, k; /* Loop counters */
373374
int n; /* Number of bytes in one line */
374375
char *z; /* General use string pointer */
375376
char **newArgv; /* New expanded g.argv under construction */
376377
char const * zFileName; /* input file name */
377
- FILE * zInFile; /* input FILE */
378
+ FILE *inFile; /* input FILE */
378379
#if defined(_WIN32)
379380
wchar_t buf[MAX_PATH];
380381
#endif
381382
382383
g.argc = argc;
@@ -402,21 +403,21 @@
402403
if( fossil_strcmp(z, "args")==0 ) break;
403404
}
404405
if( i>=g.argc-1 ) return;
405406
406407
zFileName = g.argv[i+1];
407
- zInFile = (0==strcmp("-",zFileName))
408
+ inFile = (0==strcmp("-",zFileName))
408409
? stdin
409410
: fossil_fopen(zFileName,"rb");
410
- if(!zInFile){
411
+ if(!inFile){
411412
fossil_fatal("Cannot open -args file [%s]", zFileName);
412413
}else{
413
- blob_read_from_channel(&file, zInFile, -1);
414
- if(stdin != zInFile){
415
- fclose(zInFile);
414
+ blob_read_from_channel(&file, inFile, -1);
415
+ if(stdin != inFile){
416
+ fclose(inFile);
416417
}
417
- zInFile = NULL;
418
+ inFile = NULL;
418419
}
419420
blob_to_utf8_no_bom(&file, 1);
420421
z = blob_str(&file);
421422
for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
422423
newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
@@ -586,10 +587,11 @@
586587
if( g.fSqlTrace ) g.fSqlStats = 1;
587588
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
588589
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
589590
g.zLogin = find_option("user", "U", 1);
590591
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
592
+ g.zErrlog = find_option("errorlog", 0, 1);
591593
if( find_option("utc",0,0) ) g.fTimeFormat = 1;
592594
if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
593595
if( zChdir && file_chdir(zChdir, 0) ){
594596
fossil_fatal("unable to change directories to %s", zChdir);
595597
}
@@ -605,10 +607,11 @@
605607
g.argc++;
606608
g.argv = zNewArgv;
607609
}
608610
zCmdName = g.argv[1];
609611
}
612
+ if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
610613
rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
611614
if( rc==1 ){
612615
fossil_fatal("%s: unknown command: %s\n"
613616
"%s: use \"help\" for more information\n",
614617
g.argv[0], zCmdName, g.argv[0]);
@@ -1504,10 +1507,14 @@
15041507
if( blob_buffer(&key)[0]=='#' ) continue;
15051508
if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
15061509
g.fDebug = fossil_fopen(blob_str(&value), "ab");
15071510
blob_reset(&value);
15081511
continue;
1512
+ }
1513
+ if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){
1514
+ g.zErrlog = mprintf("%s", blob_str(&value));
1515
+ continue;
15091516
}
15101517
if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
15111518
cgi_setenv("HOME", blob_str(&value));
15121519
blob_reset(&value);
15131520
continue;
15141521
--- src/main.c
+++ src/main.c
@@ -114,10 +114,11 @@
114 ** All global variables are in this structure.
115 */
116 struct Global {
117 int argc; char **argv; /* Command-line arguments to the program */
118 char *nameOfExe; /* Full path of executable. */
 
119 int isConst; /* True if the output is unchanging */
120 sqlite3 *db; /* The connection to the databases */
121 sqlite3 *dbConfig; /* Separate connection for global_config table */
122 int useAttach; /* True if global_config is attached to repository */
123 const char *zConfigDbName;/* Path of the config database. NULL if not open */
@@ -372,11 +373,11 @@
372 unsigned int i, j, k; /* Loop counters */
373 int n; /* Number of bytes in one line */
374 char *z; /* General use string pointer */
375 char **newArgv; /* New expanded g.argv under construction */
376 char const * zFileName; /* input file name */
377 FILE * zInFile; /* input FILE */
378 #if defined(_WIN32)
379 wchar_t buf[MAX_PATH];
380 #endif
381
382 g.argc = argc;
@@ -402,21 +403,21 @@
402 if( fossil_strcmp(z, "args")==0 ) break;
403 }
404 if( i>=g.argc-1 ) return;
405
406 zFileName = g.argv[i+1];
407 zInFile = (0==strcmp("-",zFileName))
408 ? stdin
409 : fossil_fopen(zFileName,"rb");
410 if(!zInFile){
411 fossil_fatal("Cannot open -args file [%s]", zFileName);
412 }else{
413 blob_read_from_channel(&file, zInFile, -1);
414 if(stdin != zInFile){
415 fclose(zInFile);
416 }
417 zInFile = NULL;
418 }
419 blob_to_utf8_no_bom(&file, 1);
420 z = blob_str(&file);
421 for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
422 newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
@@ -586,10 +587,11 @@
586 if( g.fSqlTrace ) g.fSqlStats = 1;
587 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
588 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
589 g.zLogin = find_option("user", "U", 1);
590 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
 
591 if( find_option("utc",0,0) ) g.fTimeFormat = 1;
592 if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
593 if( zChdir && file_chdir(zChdir, 0) ){
594 fossil_fatal("unable to change directories to %s", zChdir);
595 }
@@ -605,10 +607,11 @@
605 g.argc++;
606 g.argv = zNewArgv;
607 }
608 zCmdName = g.argv[1];
609 }
 
610 rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
611 if( rc==1 ){
612 fossil_fatal("%s: unknown command: %s\n"
613 "%s: use \"help\" for more information\n",
614 g.argv[0], zCmdName, g.argv[0]);
@@ -1504,10 +1507,14 @@
1504 if( blob_buffer(&key)[0]=='#' ) continue;
1505 if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
1506 g.fDebug = fossil_fopen(blob_str(&value), "ab");
1507 blob_reset(&value);
1508 continue;
 
 
 
 
1509 }
1510 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
1511 cgi_setenv("HOME", blob_str(&value));
1512 blob_reset(&value);
1513 continue;
1514
--- src/main.c
+++ src/main.c
@@ -114,10 +114,11 @@
114 ** All global variables are in this structure.
115 */
116 struct Global {
117 int argc; char **argv; /* Command-line arguments to the program */
118 char *nameOfExe; /* Full path of executable. */
119 const char *zErrlog; /* Log errors to this file, if not NULL */
120 int isConst; /* True if the output is unchanging */
121 sqlite3 *db; /* The connection to the databases */
122 sqlite3 *dbConfig; /* Separate connection for global_config table */
123 int useAttach; /* True if global_config is attached to repository */
124 const char *zConfigDbName;/* Path of the config database. NULL if not open */
@@ -372,11 +373,11 @@
373 unsigned int i, j, k; /* Loop counters */
374 int n; /* Number of bytes in one line */
375 char *z; /* General use string pointer */
376 char **newArgv; /* New expanded g.argv under construction */
377 char const * zFileName; /* input file name */
378 FILE *inFile; /* input FILE */
379 #if defined(_WIN32)
380 wchar_t buf[MAX_PATH];
381 #endif
382
383 g.argc = argc;
@@ -402,21 +403,21 @@
403 if( fossil_strcmp(z, "args")==0 ) break;
404 }
405 if( i>=g.argc-1 ) return;
406
407 zFileName = g.argv[i+1];
408 inFile = (0==strcmp("-",zFileName))
409 ? stdin
410 : fossil_fopen(zFileName,"rb");
411 if(!inFile){
412 fossil_fatal("Cannot open -args file [%s]", zFileName);
413 }else{
414 blob_read_from_channel(&file, inFile, -1);
415 if(stdin != inFile){
416 fclose(inFile);
417 }
418 inFile = NULL;
419 }
420 blob_to_utf8_no_bom(&file, 1);
421 z = blob_str(&file);
422 for(k=0, nLine=1; z[k]; k++) if( z[k]=='\n' ) nLine++;
423 newArgv = fossil_malloc( sizeof(char*)*(g.argc + nLine*2) );
@@ -586,10 +587,11 @@
587 if( g.fSqlTrace ) g.fSqlStats = 1;
588 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
589 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
590 g.zLogin = find_option("user", "U", 1);
591 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
592 g.zErrlog = find_option("errorlog", 0, 1);
593 if( find_option("utc",0,0) ) g.fTimeFormat = 1;
594 if( find_option("localtime",0,0) ) g.fTimeFormat = 2;
595 if( zChdir && file_chdir(zChdir, 0) ){
596 fossil_fatal("unable to change directories to %s", zChdir);
597 }
@@ -605,10 +607,11 @@
607 g.argc++;
608 g.argv = zNewArgv;
609 }
610 zCmdName = g.argv[1];
611 }
612 if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
613 rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
614 if( rc==1 ){
615 fossil_fatal("%s: unknown command: %s\n"
616 "%s: use \"help\" for more information\n",
617 g.argv[0], zCmdName, g.argv[0]);
@@ -1504,10 +1507,14 @@
1507 if( blob_buffer(&key)[0]=='#' ) continue;
1508 if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
1509 g.fDebug = fossil_fopen(blob_str(&value), "ab");
1510 blob_reset(&value);
1511 continue;
1512 }
1513 if( blob_eq(&key, "errorlog:") && blob_token(&line, &value) ){
1514 g.zErrlog = mprintf("%s", blob_str(&value));
1515 continue;
1516 }
1517 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
1518 cgi_setenv("HOME", blob_str(&value));
1519 blob_reset(&value);
1520 continue;
1521
+38
--- src/printf.c
+++ src/printf.c
@@ -22,10 +22,11 @@
2222
#include "printf.h"
2323
#if defined(_WIN32)
2424
# include <io.h>
2525
# include <fcntl.h>
2626
#endif
27
+#include <time.h>
2728
2829
/*
2930
** Conversion types fall into various categories as defined by the
3031
** following enumeration.
3132
*/
@@ -906,10 +907,43 @@
906907
fossil_puts(blob_str(&b), 1);
907908
blob_reset(&b);
908909
va_end(ap);
909910
}
910911
912
+/*
913
+** Write a message to the error log, if the error log filename is
914
+** defined.
915
+*/
916
+static void fossil_errorlog(const char *zFormat, ...){
917
+ struct tm *pNow;
918
+ time_t now;
919
+ FILE *out;
920
+ const char *z;
921
+ int i;
922
+ va_list ap;
923
+ static const char *azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
924
+ "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
925
+ "REQUEST_URI", "SCRIPT_NAME" };
926
+ if( g.zErrlog==0 ) return;
927
+ out = fopen(g.zErrlog, "a");
928
+ if( out==0 ) return;
929
+ now = time(0);
930
+ pNow = gmtime(&now);
931
+ fprintf(out, "------------- %04d-%02d-%02d %02d:%02d:%02d UTC ------------\n",
932
+ pNow->tm_year+1900, pNow->tm_mon+1, pNow->tm_mday+1,
933
+ pNow->tm_hour, pNow->tm_min, pNow->tm_sec);
934
+ va_start(ap, zFormat);
935
+ vfprintf(out, zFormat, ap);
936
+ fprintf(out, "\n");
937
+ va_end(ap);
938
+ for(i=0; i<sizeof(azEnv)/sizeof(azEnv[0]); i++){
939
+ if( (z = getenv(azEnv[i]))!=0 || (z = P(azEnv[i]))!=0 ){
940
+ fprintf(out, "%s=%s\n", azEnv[i], z);
941
+ }
942
+ }
943
+ fclose(out);
944
+}
911945
912946
/*
913947
** The following variable becomes true while processing a fatal error
914948
** or a panic. If additional "recursive-fatal" errors occur while
915949
** shutting down, the recursive errors are silently ignored.
@@ -931,10 +965,11 @@
931965
mainInFatalError = 1;
932966
db_force_rollback();
933967
va_start(ap, zFormat);
934968
sqlite3_vsnprintf(sizeof(z),z,zFormat, ap);
935969
va_end(ap);
970
+ fossil_errorlog("panic: %s", z);
936971
#ifdef FOSSIL_ENABLE_JSON
937972
if( g.json.isJsonMode ){
938973
json_err( 0, z, 1 );
939974
if( g.isHTTP ){
940975
rc = 0 /* avoid HTTP 500 */;
@@ -962,10 +997,11 @@
962997
va_list ap;
963998
mainInFatalError = 1;
964999
va_start(ap, zFormat);
9651000
z = vmprintf(zFormat, ap);
9661001
va_end(ap);
1002
+ fossil_errorlog("fatal: %s", z);
9671003
#ifdef FOSSIL_ENABLE_JSON
9681004
if( g.json.isJsonMode ){
9691005
json_err( g.json.resultCode, z, 1 );
9701006
if( g.isHTTP ){
9711007
rc = 0 /* avoid HTTP 500 */;
@@ -1004,10 +1040,11 @@
10041040
if( mainInFatalError ) return;
10051041
mainInFatalError = 1;
10061042
va_start(ap, zFormat);
10071043
z = vmprintf(zFormat, ap);
10081044
va_end(ap);
1045
+ fossil_errorlog("fatal: %s", z);
10091046
#ifdef FOSSIL_ENABLE_JSON
10101047
if( g.json.isJsonMode ){
10111048
json_err( g.json.resultCode, z, 1 );
10121049
if( g.isHTTP ){
10131050
rc = 0 /* avoid HTTP 500 */;
@@ -1034,10 +1071,11 @@
10341071
char *z;
10351072
va_list ap;
10361073
va_start(ap, zFormat);
10371074
z = vmprintf(zFormat, ap);
10381075
va_end(ap);
1076
+ fossil_errorlog("warning: %s", z);
10391077
#ifdef FOSSIL_ENABLE_JSON
10401078
if(g.json.isJsonMode){
10411079
json_warn( FSL_JSON_W_UNKNOWN, z );
10421080
}else
10431081
#endif
10441082
--- src/printf.c
+++ src/printf.c
@@ -22,10 +22,11 @@
22 #include "printf.h"
23 #if defined(_WIN32)
24 # include <io.h>
25 # include <fcntl.h>
26 #endif
 
27
28 /*
29 ** Conversion types fall into various categories as defined by the
30 ** following enumeration.
31 */
@@ -906,10 +907,43 @@
906 fossil_puts(blob_str(&b), 1);
907 blob_reset(&b);
908 va_end(ap);
909 }
910
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
911
912 /*
913 ** The following variable becomes true while processing a fatal error
914 ** or a panic. If additional "recursive-fatal" errors occur while
915 ** shutting down, the recursive errors are silently ignored.
@@ -931,10 +965,11 @@
931 mainInFatalError = 1;
932 db_force_rollback();
933 va_start(ap, zFormat);
934 sqlite3_vsnprintf(sizeof(z),z,zFormat, ap);
935 va_end(ap);
 
936 #ifdef FOSSIL_ENABLE_JSON
937 if( g.json.isJsonMode ){
938 json_err( 0, z, 1 );
939 if( g.isHTTP ){
940 rc = 0 /* avoid HTTP 500 */;
@@ -962,10 +997,11 @@
962 va_list ap;
963 mainInFatalError = 1;
964 va_start(ap, zFormat);
965 z = vmprintf(zFormat, ap);
966 va_end(ap);
 
967 #ifdef FOSSIL_ENABLE_JSON
968 if( g.json.isJsonMode ){
969 json_err( g.json.resultCode, z, 1 );
970 if( g.isHTTP ){
971 rc = 0 /* avoid HTTP 500 */;
@@ -1004,10 +1040,11 @@
1004 if( mainInFatalError ) return;
1005 mainInFatalError = 1;
1006 va_start(ap, zFormat);
1007 z = vmprintf(zFormat, ap);
1008 va_end(ap);
 
1009 #ifdef FOSSIL_ENABLE_JSON
1010 if( g.json.isJsonMode ){
1011 json_err( g.json.resultCode, z, 1 );
1012 if( g.isHTTP ){
1013 rc = 0 /* avoid HTTP 500 */;
@@ -1034,10 +1071,11 @@
1034 char *z;
1035 va_list ap;
1036 va_start(ap, zFormat);
1037 z = vmprintf(zFormat, ap);
1038 va_end(ap);
 
1039 #ifdef FOSSIL_ENABLE_JSON
1040 if(g.json.isJsonMode){
1041 json_warn( FSL_JSON_W_UNKNOWN, z );
1042 }else
1043 #endif
1044
--- src/printf.c
+++ src/printf.c
@@ -22,10 +22,11 @@
22 #include "printf.h"
23 #if defined(_WIN32)
24 # include <io.h>
25 # include <fcntl.h>
26 #endif
27 #include <time.h>
28
29 /*
30 ** Conversion types fall into various categories as defined by the
31 ** following enumeration.
32 */
@@ -906,10 +907,43 @@
907 fossil_puts(blob_str(&b), 1);
908 blob_reset(&b);
909 va_end(ap);
910 }
911
912 /*
913 ** Write a message to the error log, if the error log filename is
914 ** defined.
915 */
916 static void fossil_errorlog(const char *zFormat, ...){
917 struct tm *pNow;
918 time_t now;
919 FILE *out;
920 const char *z;
921 int i;
922 va_list ap;
923 static const char *azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
924 "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
925 "REQUEST_URI", "SCRIPT_NAME" };
926 if( g.zErrlog==0 ) return;
927 out = fopen(g.zErrlog, "a");
928 if( out==0 ) return;
929 now = time(0);
930 pNow = gmtime(&now);
931 fprintf(out, "------------- %04d-%02d-%02d %02d:%02d:%02d UTC ------------\n",
932 pNow->tm_year+1900, pNow->tm_mon+1, pNow->tm_mday+1,
933 pNow->tm_hour, pNow->tm_min, pNow->tm_sec);
934 va_start(ap, zFormat);
935 vfprintf(out, zFormat, ap);
936 fprintf(out, "\n");
937 va_end(ap);
938 for(i=0; i<sizeof(azEnv)/sizeof(azEnv[0]); i++){
939 if( (z = getenv(azEnv[i]))!=0 || (z = P(azEnv[i]))!=0 ){
940 fprintf(out, "%s=%s\n", azEnv[i], z);
941 }
942 }
943 fclose(out);
944 }
945
946 /*
947 ** The following variable becomes true while processing a fatal error
948 ** or a panic. If additional "recursive-fatal" errors occur while
949 ** shutting down, the recursive errors are silently ignored.
@@ -931,10 +965,11 @@
965 mainInFatalError = 1;
966 db_force_rollback();
967 va_start(ap, zFormat);
968 sqlite3_vsnprintf(sizeof(z),z,zFormat, ap);
969 va_end(ap);
970 fossil_errorlog("panic: %s", z);
971 #ifdef FOSSIL_ENABLE_JSON
972 if( g.json.isJsonMode ){
973 json_err( 0, z, 1 );
974 if( g.isHTTP ){
975 rc = 0 /* avoid HTTP 500 */;
@@ -962,10 +997,11 @@
997 va_list ap;
998 mainInFatalError = 1;
999 va_start(ap, zFormat);
1000 z = vmprintf(zFormat, ap);
1001 va_end(ap);
1002 fossil_errorlog("fatal: %s", z);
1003 #ifdef FOSSIL_ENABLE_JSON
1004 if( g.json.isJsonMode ){
1005 json_err( g.json.resultCode, z, 1 );
1006 if( g.isHTTP ){
1007 rc = 0 /* avoid HTTP 500 */;
@@ -1004,10 +1040,11 @@
1040 if( mainInFatalError ) return;
1041 mainInFatalError = 1;
1042 va_start(ap, zFormat);
1043 z = vmprintf(zFormat, ap);
1044 va_end(ap);
1045 fossil_errorlog("fatal: %s", z);
1046 #ifdef FOSSIL_ENABLE_JSON
1047 if( g.json.isJsonMode ){
1048 json_err( g.json.resultCode, z, 1 );
1049 if( g.isHTTP ){
1050 rc = 0 /* avoid HTTP 500 */;
@@ -1034,10 +1071,11 @@
1071 char *z;
1072 va_list ap;
1073 va_start(ap, zFormat);
1074 z = vmprintf(zFormat, ap);
1075 va_end(ap);
1076 fossil_errorlog("warning: %s", z);
1077 #ifdef FOSSIL_ENABLE_JSON
1078 if(g.json.isJsonMode){
1079 json_warn( FSL_JSON_W_UNKNOWN, z );
1080 }else
1081 #endif
1082
--- src/style.c
+++ src/style.c
@@ -1207,10 +1207,11 @@
12071207
if( g.perm.Setup ){
12081208
const char *zRedir = P("redirect");
12091209
if( zRedir ) cgi_redirect(zRedir);
12101210
}
12111211
style_footer();
1212
+ if( g.perm.Admin && P("err") ) fossil_fatal("%s", P("err"));
12121213
}
12131214
12141215
/*
12151216
** This page is a honeypot for spiders and bots.
12161217
**
12171218
--- src/style.c
+++ src/style.c
@@ -1207,10 +1207,11 @@
1207 if( g.perm.Setup ){
1208 const char *zRedir = P("redirect");
1209 if( zRedir ) cgi_redirect(zRedir);
1210 }
1211 style_footer();
 
1212 }
1213
1214 /*
1215 ** This page is a honeypot for spiders and bots.
1216 **
1217
--- src/style.c
+++ src/style.c
@@ -1207,10 +1207,11 @@
1207 if( g.perm.Setup ){
1208 const char *zRedir = P("redirect");
1209 if( zRedir ) cgi_redirect(zRedir);
1210 }
1211 style_footer();
1212 if( g.perm.Admin && P("err") ) fossil_fatal("%s", P("err"));
1213 }
1214
1215 /*
1216 ** This page is a honeypot for spiders and bots.
1217 **
1218
+15
--- src/util.c
+++ src/util.c
@@ -26,10 +26,13 @@
2626
#ifdef _WIN32
2727
# include <windows.h>
2828
#else
2929
# include <sys/time.h>
3030
# include <sys/resource.h>
31
+# include <unistd.h>
32
+# include <fcntl.h>
33
+# include <errno.h>
3134
#endif
3235
3336
3437
/*
3538
** Exit. Take care to close the database first.
@@ -299,5 +302,17 @@
299302
int const rc = fossilTimerList[timerId-1].id;
300303
assert(!rc || (rc == timerId));
301304
return fossilTimerList[timerId-1].id;
302305
}
303306
}
307
+
308
+/*
309
+** Return TRUE if fd is a valid open file descriptor. This only
310
+** works on unix. The function always returns true on Windows.
311
+*/
312
+int is_valid_fd(int fd){
313
+#ifdef _WIN32
314
+ return 1;
315
+#else
316
+ return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
317
+#endif
318
+}
304319
--- src/util.c
+++ src/util.c
@@ -26,10 +26,13 @@
26 #ifdef _WIN32
27 # include <windows.h>
28 #else
29 # include <sys/time.h>
30 # include <sys/resource.h>
 
 
 
31 #endif
32
33
34 /*
35 ** Exit. Take care to close the database first.
@@ -299,5 +302,17 @@
299 int const rc = fossilTimerList[timerId-1].id;
300 assert(!rc || (rc == timerId));
301 return fossilTimerList[timerId-1].id;
302 }
303 }
 
 
 
 
 
 
 
 
 
 
 
 
304
--- src/util.c
+++ src/util.c
@@ -26,10 +26,13 @@
26 #ifdef _WIN32
27 # include <windows.h>
28 #else
29 # include <sys/time.h>
30 # include <sys/resource.h>
31 # include <unistd.h>
32 # include <fcntl.h>
33 # include <errno.h>
34 #endif
35
36
37 /*
38 ** Exit. Take care to close the database first.
@@ -299,5 +302,17 @@
302 int const rc = fossilTimerList[timerId-1].id;
303 assert(!rc || (rc == timerId));
304 return fossilTimerList[timerId-1].id;
305 }
306 }
307
308 /*
309 ** Return TRUE if fd is a valid open file descriptor. This only
310 ** works on unix. The function always returns true on Windows.
311 */
312 int is_valid_fd(int fd){
313 #ifdef _WIN32
314 return 1;
315 #else
316 return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
317 #endif
318 }
319

Keyboard Shortcuts

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