00001 /* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #include "log.h" 00018 00019 #include <my_global.h> 00020 #include <m_string.h> 00021 #include <my_sys.h> 00022 00023 #include <stdarg.h> 00024 00025 #include "portability.h" /* for vsnprintf() on Windows. */ 00026 00027 /* 00028 TODO: 00029 - add flexible header support 00030 - rewrite all fprintf with fwrite 00031 - think about using 'write' instead of fwrite/fprintf on POSIX systems 00032 */ 00033 00034 /* 00035 Format log entry and write it to the given stream. 00036 SYNOPSYS 00037 log() 00038 */ 00039 00040 static inline void log(FILE *file, const char *format, va_list args) 00041 { 00042 /* 00043 log() should be thread-safe; it implies that we either call fprintf() 00044 once per log(), or use flockfile()/funlockfile(). But flockfile() is 00045 POSIX, not ANSI C, so we try to vsnprintf the whole message to the 00046 stack, and if stack buffer is not enough, to malloced string. When 00047 message is formatted, it is fprintf()'ed to the file. 00048 */ 00049 00050 /* Format time like MYSQL_LOG does. */ 00051 time_t now= time(0); 00052 struct tm bd_time; // broken-down time 00053 localtime_r(&now, &bd_time); 00054 00055 char buff_date[32]; 00056 sprintf(buff_date, "%02d%02d%02d %2d:%02d:%02d\t", 00057 bd_time.tm_year % 100, 00058 bd_time.tm_mon + 1, 00059 bd_time.tm_mday, 00060 bd_time.tm_hour, 00061 bd_time.tm_min, 00062 bd_time.tm_sec); 00063 /* Format the message */ 00064 char buff_stack[256]; 00065 00066 int n= vsnprintf(buff_stack, sizeof(buff_stack), format, args); 00067 /* 00068 return value of vsnprintf can vary, according to various standards; 00069 try to check all cases. 00070 */ 00071 char *buff_msg= buff_stack; 00072 if (n < 0 || n == sizeof(buff_stack)) 00073 { 00074 int size= sizeof(buff_stack) * 2; 00075 buff_msg= (char*) my_malloc(size, MYF(0)); 00076 while (TRUE) 00077 { 00078 if (buff_msg == 0) 00079 { 00080 strmake(buff_stack, "log(): message is too big, my_malloc() failed", 00081 sizeof(buff_stack) - 1); 00082 buff_msg= buff_stack; 00083 break; 00084 } 00085 n = vsnprintf(buff_msg, size, format, args); 00086 if (n >= 0 && n < size) 00087 break; 00088 size*= 2; 00089 /* realloc() does unnecessary memcpy */ 00090 my_free(buff_msg, 0); 00091 buff_msg= (char*) my_malloc(size, MYF(0)); 00092 } 00093 } 00094 else if ((size_t) n > sizeof(buff_stack)) 00095 { 00096 buff_msg= (char*) my_malloc(n + 1, MYF(0)); 00097 #ifdef DBUG 00098 DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args)); 00099 #else 00100 vsnprintf(buff_msg, n + 1, format, args); 00101 #endif 00102 } 00103 fprintf(file, "%s%s\n", buff_date, buff_msg); 00104 if (buff_msg != buff_stack) 00105 my_free(buff_msg, 0); 00106 00107 /* don't fflush() the file: buffering strategy is set in log_init() */ 00108 } 00109 00110 00111 void log_error(const char *format, ...) 00112 { 00113 va_list args; 00114 va_start(args, format); 00115 log(stderr, format, args); 00116 va_end(args); 00117 } 00118 00119 00120 void log_info(const char *format, ...) 00121 { 00122 va_list args; 00123 va_start(args, format); 00124 log(stdout, format, args); 00125 va_end(args); 00126 } 00127 00128 /* TODO: rewrite with buffering print */ 00129 void print_info(const char *format, ...) 00130 { 00131 va_list args; 00132 va_start(args, format); 00133 vfprintf(stdout, format, args); 00134 va_end(args); 00135 } 00136 00137 void print_error(const char *format, ...) 00138 { 00139 va_list args; 00140 va_start(args, format); 00141 vfprintf(stderr, format, args); 00142 va_end(args); 00143 } 00144 00145 /* 00146 log_init() 00147 RETURN VALUE 00148 0 ok 00149 !0 error 00150 */ 00151 00152 void log_init() 00153 { 00154 /* 00155 stderr is unbuffered by default; there is no good of line buffering, 00156 as all logging is performed linewise - so remove buffering from stdout 00157 also 00158 */ 00159 setbuf(stdout, 0); 00160 } 00161 00162 void die(const char *format, ...) 00163 { 00164 va_list args; 00165 fprintf(stderr,"%s: ", my_progname); 00166 va_start(args, format); 00167 vfprintf(stderr, format, args); 00168 va_end(args); 00169 fprintf(stderr, "\n"); 00170 exit(1); 00171 }
1.4.7

