updates.
[silc.git] / lib / silcutil / silclog.c
1 /*
2
3   silclog.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "silcincludes.h"
23
24 /* Set TRUE/FALSE to enable/disable debugging */
25 bool silc_debug = FALSE;
26 bool silc_debug_hexdump = FALSE;
27 char *silc_debug_string = NULL;
28
29 /* SILC Log name strings. These strings are printed to the log file. */
30 const SilcLogTypeName silc_log_types[] =
31 {
32   { "Info", SILC_LOG_INFO },
33   { "Warning", SILC_LOG_WARNING },
34   { "Error", SILC_LOG_ERROR },
35   { "Fatal", SILC_LOG_FATAL },
36
37   { NULL, -1 },
38 };
39
40 char *log_info_file;
41 char *log_warning_file;
42 char *log_error_file;
43 char *log_fatal_file;
44 uint32 log_info_size;
45 uint32 log_warning_size;
46 uint32 log_error_size;
47 uint32 log_fatal_size;
48
49 /* Log callbacks. If these are set by the application these are used
50    instead of the default functions in this file. */
51 static SilcLogCb info_cb = NULL;
52 static SilcLogCb warning_cb = NULL;
53 static SilcLogCb error_cb = NULL;
54 static SilcLogCb fatal_cb = NULL;
55
56 /* Debug callbacks. If set these are used instead of default ones. */
57 static SilcDebugCb debug_cb = NULL;
58 static SilcDebugHexdumpCb debug_hexdump_cb = NULL;
59
60 /* Outputs the log message to what ever log file selected. */
61
62 void silc_log_output(const char *filename, uint32 maxsize,
63                      SilcLogType type, char *string)
64 {
65   FILE *fp;
66   const SilcLogTypeName *np;
67
68   switch(type)
69     {
70     case SILC_LOG_INFO:
71       if (info_cb) {
72         (*info_cb)(string);
73         silc_free(string);
74         return;
75       }
76       break;
77     case SILC_LOG_WARNING:
78       if (warning_cb) {
79         (*warning_cb)(string);
80         silc_free(string);
81         return;
82       }
83       break;
84     case SILC_LOG_ERROR:
85       if (error_cb) {
86         (*error_cb)(string);
87         silc_free(string);
88         return;
89       }
90       break;
91     case SILC_LOG_FATAL:
92       if (fatal_cb) {
93         (*fatal_cb)(string);
94         silc_free(string);
95         return;
96       }
97       break;
98     }
99
100   if (!filename)
101     fp = stderr;
102   else {
103     /* Purge the log file if the max size is defined. */
104     if (maxsize) {
105       fp = fopen(filename, "r");
106       if (fp) {
107         int filelen;
108         
109         filelen = fseek(fp, (off_t)0L, SEEK_END);
110         fseek(fp, (off_t)0L, SEEK_SET);  
111         
112         /* Purge? */
113         if (filelen >= maxsize)
114           unlink(filename);
115         
116         fclose(fp);
117       }
118     }
119     
120     /* Open the log file */
121     if ((fp = fopen(filename, "a+")) == NULL) {
122       fprintf(stderr, "warning: could not open log file "
123               "%s: %s\n", filename, strerror(errno));
124       fprintf(stderr, "warning: log messages will be displayed on "
125               "the screen\n");
126       fp = stderr;
127     }
128   }
129
130   /* Get the log type name */
131   for (np = silc_log_types; np->name; np++) {
132     if (np->type == type)
133       break;
134   }
135
136   fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), np->name, string);
137   fflush(fp);
138   if (fp != stderr)
139     fclose(fp);
140   silc_free(string);
141 }
142
143 /* Outputs the debug message to stderr. */
144
145 void silc_log_output_debug(char *file, char *function, 
146                            int line, char *string)
147 {
148   if (!silc_debug) {
149     silc_free(string);
150     return;
151   }
152
153   if (silc_debug_string && 
154       (!silc_string_regex_match(silc_debug_string, file) &&
155        !silc_string_regex_match(silc_debug_string, function))) {
156     silc_free(string);
157     return;
158   }
159
160   if (debug_cb)
161     {
162       (*debug_cb)(file, function, line, string);
163       silc_free(string);
164       return;
165     }
166
167   fprintf(stderr, "%s:%d: %s\n", function, line, string);
168   fflush(stderr);
169   silc_free(string);
170 }
171
172 /* Hexdumps a message */
173
174 void silc_log_output_hexdump(char *file, char *function, 
175                              int line, void *data_in,
176                              uint32 len, char *string)
177 {
178   int i, k;
179   int off, pos, count;
180   unsigned char *data = (unsigned char *)data_in;
181
182   if (!silc_debug_hexdump) {
183     silc_free(string);
184     return;
185   }
186
187   if (silc_debug_string && 
188       (!silc_string_regex_match(silc_debug_string, file) &&
189        !silc_string_regex_match(silc_debug_string, function))) {
190     silc_free(string);
191     return;
192   }
193
194   if (debug_hexdump_cb)
195     {
196       (*debug_hexdump_cb)(file, function, line, data_in, len, string);
197       silc_free(string);
198       return;
199     }
200
201   fprintf(stderr, "%s:%d: %s\n", function, line, string);
202   silc_free(string);
203
204   k = 0;
205   off = len % 16;
206   pos = 0;
207   count = 16;
208   while (1) {
209
210     if (off) {
211       if ((len - pos) < 16 && (len - pos <= len - off))
212         count = off;
213     } else {
214       if (pos == len)
215         count = 0;
216     }
217     if (off == len)
218       count = len;
219
220     if (count)
221       fprintf(stderr, "%08X  ", k++ * 16);
222
223     for (i = 0; i < count; i++) {
224       fprintf(stderr, "%02X ", data[pos + i]);
225       
226       if ((i + 1) % 4 == 0)
227         fprintf(stderr, " ");
228     }
229
230     if (count && count < 16) {
231       int j;
232       
233       for (j = 0; j < 16 - count; j++) {
234         fprintf(stderr, "   ");
235
236         if ((j + count + 1) % 4 == 0)
237           fprintf(stderr, " ");
238       }
239     }
240   
241     for (i = 0; i < count; i++) {
242       char ch;
243       
244       if (data[pos] < 32 || data[pos] >= 127)
245         ch = '.';
246       else
247         ch = data[pos];
248
249       fprintf(stderr, "%c", ch);
250       pos++;
251     }
252
253     if (count)
254       fprintf(stderr, "\n");
255
256     if (count < 16)
257       break;
258   }
259 }
260
261 /* Sets log files */
262
263 void silc_log_set_files(char *info, uint32 info_size, 
264                         char *warning, uint32 warning_size,
265                         char *error, uint32 error_size,
266                         char *fatal, uint32 fatal_size)
267 {
268   log_info_file = info;
269   log_warning_file = warning;
270   log_error_file = error;
271   log_fatal_file = fatal;
272
273   log_info_size = info_size;
274   log_warning_size = warning_size;
275   log_error_size = error_size;
276   log_fatal_size = fatal_size;
277 }
278
279 /* Sets log callbacks */
280
281 void silc_log_set_callbacks(SilcLogCb info, SilcLogCb warning,
282                             SilcLogCb error, SilcLogCb fatal)
283 {
284   info_cb = info;
285   warning_cb = warning;
286   error_cb = error;
287   fatal_cb = fatal;
288 }
289
290 /* Resets log callbacks */
291
292 void silc_log_reset_callbacks()
293 {
294   info_cb = warning_cb = error_cb = fatal_cb = NULL;
295 }
296
297 /* Sets debug callbacks */
298
299 void silc_log_set_debug_callbacks(SilcDebugCb debug, 
300                                   SilcDebugHexdumpCb debug_hexdump)
301 {
302   debug_cb = debug;
303   debug_hexdump_cb = debug_hexdump;
304 }
305
306 /* Resets debug callbacks */
307
308 void silc_log_reset_debug_callbacks()
309 {
310   debug_cb = NULL;
311   debug_hexdump_cb = NULL;
312 }
313
314 /* Set current debug string */
315
316 void silc_log_set_debug_string(const char *debug_string)
317 {
318   silc_free(silc_debug_string);
319   if (strchr(debug_string, '(') &&
320       strchr(debug_string, ')'))
321     silc_debug_string = strdup(debug_string);
322   else
323     silc_debug_string = silc_string_regexify(debug_string);
324 }