A LOT updates. Cannot separate. :)
[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 int silc_debug = FALSE;
26
27 /* SILC Log name strings. These strings are printed to the log file. */
28 const SilcLogTypeName silc_log_types[] =
29 {
30   { "Info", SILC_LOG_INFO },
31   { "Warning", SILC_LOG_WARNING },
32   { "Error", SILC_LOG_ERROR },
33   { "Fatal", SILC_LOG_FATAL },
34
35   { NULL, -1 },
36 };
37
38 char *log_info_file;
39 char *log_warning_file;
40 char *log_error_file;
41 char *log_fatal_file;
42 unsigned int log_info_size;
43 unsigned int log_warning_size;
44 unsigned int log_error_size;
45 unsigned int log_fatal_size;
46
47 /* Log callbacks. If these are set by the application these are used
48    instead of the default functions in this file. */
49 static SilcLogCb info_cb = NULL;
50 static SilcLogCb warning_cb = NULL;
51 static SilcLogCb error_cb = NULL;
52 static SilcLogCb fatal_cb = NULL;
53
54 /* Debug callbacks. If set these are used instead of default ones. */
55 static SilcDebugCb debug_cb = NULL;
56 static SilcDebugHexdumpCb debug_hexdump_cb = NULL;
57
58 /* Outputs the log message to what ever log file selected. */
59
60 void silc_log_output(const char *filename, unsigned int maxsize,
61                      SilcLogType type, char *string)
62 {
63   FILE *fp;
64   const SilcLogTypeName *np;
65
66   switch(type)
67     {
68     case SILC_LOG_INFO:
69       if (info_cb) {
70         (*info_cb)(string);
71         silc_free(string);
72         return;
73       }
74       break;
75     case SILC_LOG_WARNING:
76       if (warning_cb) {
77         (*warning_cb)(string);
78         silc_free(string);
79         return;
80       }
81       break;
82     case SILC_LOG_ERROR:
83       if (error_cb) {
84         (*error_cb)(string);
85         silc_free(string);
86         return;
87       }
88       break;
89     case SILC_LOG_FATAL:
90       if (fatal_cb) {
91         (*fatal_cb)(string);
92         silc_free(string);
93         return;
94       }
95       break;
96     }
97
98   /* Purge the log file if the max size is defined. */
99   if (maxsize) {
100     fp = fopen(filename, "r");
101     if (fp) {
102       int filelen;
103       
104       filelen = fseek(fp, (off_t)0L, SEEK_END);
105       fseek(fp, (off_t)0L, SEEK_SET);  
106       
107       /* Purge? */
108       if (filelen >= maxsize)
109         unlink(filename);
110     }
111   }
112
113   /* Open the log file */
114   if ((fp = fopen(filename, "a+")) == NULL) {
115     fprintf(stderr, "warning: could not open log file "
116             "%s: %s\n", filename, strerror(errno));
117     fprintf(stderr, "warning: log messages will be displayed on the screen\n");
118     fp = stderr;
119   }
120  
121   /* Get the log type name */
122   for(np = silc_log_types; np->name; np++) {
123     if (np->type == type)
124       break;
125   }
126
127   fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), np->name, string);
128   fflush(fp);
129   fclose(fp);
130   silc_free(string);
131 }
132
133 /* Outputs the debug message to stderr. */
134
135 void silc_log_output_debug(char *file, char *function, 
136                            int line, char *string)
137 {
138   if (!silc_debug) {
139     silc_free(string);
140     return;
141   }
142
143   if (debug_cb)
144     {
145       (*debug_cb)(file, function, line, string);
146       silc_free(string);
147       return;
148     }
149
150   /* fprintf(stderr, "%s:%s:%d: %s\n", file, function, line, string); */
151   fprintf(stderr, "%s:%d: %s\n", function, line, string);
152   fflush(stderr);
153   silc_free(string);
154 }
155
156 /* Hexdumps a message */
157
158 void silc_log_output_hexdump(char *file, char *function, 
159                              int line, void *data_in,
160                              unsigned int len, char *string)
161 {
162   int i, k;
163   int off, pos, count;
164   unsigned char *data = (unsigned char *)data_in;
165
166   if (!silc_debug) {
167     silc_free(string);
168     return;
169   }
170
171   if (debug_hexdump_cb)
172     {
173       (*debug_hexdump_cb)(file, function, line, data_in, len, string);
174       silc_free(string);
175       return;
176     }
177
178   /* fprintf(stderr, "%s:%s:%d: %s\n", file, function, line, string); */
179   fprintf(stderr, "%s:%d: %s\n", function, line, string);
180   silc_free(string);
181
182   k = 0;
183   off = len % 16;
184   pos = 0;
185   count = 16;
186   while (1) {
187
188     if (off) {
189       if ((len - pos) < 16 && (len - pos <= len - off))
190         count = off;
191     } else {
192       if (pos == len)
193         count = 0;
194     }
195     if (off == len)
196       count = len;
197
198     if (count)
199       fprintf(stderr, "%08X  ", k++ * 16);
200
201     for (i = 0; i < count; i++) {
202       fprintf(stderr, "%02X ", data[pos + i]);
203       
204       if ((i + 1) % 4 == 0)
205         fprintf(stderr, " ");
206     }
207
208     if (count && count < 16) {
209       int j;
210       
211       for (j = 0; j < 16 - count; j++) {
212         fprintf(stderr, "   ");
213
214         if ((j + count + 1) % 4 == 0)
215           fprintf(stderr, " ");
216       }
217     }
218   
219     for (i = 0; i < count; i++) {
220       char ch;
221       
222       if (data[pos] < 32 || data[pos] >= 127)
223         ch = '.';
224       else
225         ch = data[pos];
226
227       fprintf(stderr, "%c", ch);
228       pos++;
229     }
230
231     if (count)
232       fprintf(stderr, "\n");
233
234     if (count < 16)
235       break;
236   }
237 }
238
239 /* Sets log files */
240
241 void silc_log_set_files(char *info, unsigned int info_size, 
242                         char *warning, unsigned int warning_size,
243                         char *error, unsigned int error_size,
244                         char *fatal, unsigned int fatal_size)
245 {
246   log_info_file = info;
247   log_warning_file = warning;
248   log_error_file = error;
249   log_fatal_file = fatal;
250
251   log_info_size = info_size;
252   log_warning_size = warning_size;
253   log_error_size = error_size;
254   log_fatal_size = fatal_size;
255 }
256
257 /* Sets log callbacks */
258
259 void silc_log_set_callbacks(SilcLogCb info, SilcLogCb warning,
260                             SilcLogCb error, SilcLogCb fatal)
261 {
262   info_cb = info;
263   warning_cb = warning;
264   error_cb = error;
265   fatal_cb = fatal;
266 }
267
268 /* Resets log callbacks */
269
270 void silc_log_reset_callbacks()
271 {
272   info_cb = warning_cb = error_cb = fatal_cb = NULL;
273 }
274
275 /* Sets debug callbacks */
276
277 void silc_log_set_debug_callbacks(SilcDebugCb debug, 
278                                   SilcDebugHexdumpCb debug_hexdump)
279 {
280   debug_cb = debug;
281   debug_hexdump_cb = debug_hexdump;
282 }
283
284 /* Resets debug callbacks */
285
286 void silc_log_reset_debug_callbacks()
287 {
288   debug_cb = NULL;
289   debug_hexdump_cb = NULL;
290 }