b1ad9186d332d234f0a89ff21c2558415496da89
[silc.git] / lib / silccore / 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 /*
21  * $Id$
22  * $Log$
23  * Revision 1.5  2000/07/17 16:46:37  priikone
24  *      Still bug fix in silc_log_format :)
25  *
26  * Revision 1.4  2000/07/17 16:44:57  priikone
27  *      Buffer overflow bug fixe in silc_log_format.
28  *
29  * Revision 1.3  2000/07/05 06:06:35  priikone
30  *      Global cosmetic change.
31  *
32  * Revision 1.2  2000/07/03 05:53:58  priikone
33  *      Fixed file purging bug.  The purging should work now ok.
34  *
35  * Revision 1.1.1.1  2000/06/27 11:36:55  priikone
36  *      Imported from internal CVS/Added Log headers.
37  *
38  *
39  */
40
41 #include "silcincludes.h"
42
43 /* SILC Log name strings. These strings are printed to the log file. */
44 const SilcLogTypeName silc_log_types[] =
45 {
46   { "Info", SILC_LOG_INFO },
47   { "Warning", SILC_LOG_WARNING },
48   { "Error", SILC_LOG_ERROR },
49   { "Fatal", SILC_LOG_FATAL },
50
51   { NULL, -1 },
52 };
53
54 char *log_info_file;
55 char *log_warning_file;
56 char *log_error_file;
57 char *log_fatal_file;
58 unsigned int log_info_size;
59 unsigned int log_warning_size;
60 unsigned int log_error_size;
61 unsigned int log_fatal_size;
62
63 /* Formats arguments to a string and returns it after allocating memory
64    for it. It must be remembered to free it later. */
65
66 char *silc_log_format(char *fmt, ...)
67 {
68   va_list args;
69   static char buf[8192];
70
71   memset(buf, 0, sizeof(buf));
72   va_start(args, fmt);
73   vsnprintf(buf, sizeof(buf) - 1, fmt, args);
74   va_end(args);
75
76   return strdup(buf);
77 }
78
79 /* Outputs the log message to what ever log file selected. */
80
81 void silc_log_output(const char *filename, unsigned int maxsize,
82                      SilcLogType type, char *string)
83 {
84   FILE *fp;
85   const SilcLogTypeName *np;
86
87   /* Purge the log file if the max size is defined. */
88   if (maxsize) {
89     fp = fopen(filename, "r");
90     if (fp) {
91       int filelen;
92       
93       filelen = fseek(fp, (off_t)0L, SEEK_END);
94       fseek(fp, (off_t)0L, SEEK_SET);  
95       
96       /* Purge? */
97       if (filelen >= maxsize)
98         unlink(filename);
99     }
100   }
101
102   /* Open the log file */
103   if ((fp = fopen(filename, "a+")) == NULL) {
104     fprintf(stderr, "warning: could not open log file "
105             "%s: %s\n", filename, strerror(errno));
106     fprintf(stderr, "warning: log messages will be displayed on the screen\n");
107     fp = stderr;
108   }
109  
110   /* Get the log type name */
111   for(np = silc_log_types; np->name; np++) {
112     if (np->type == type)
113       break;
114   }
115
116   fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), np->name, string);
117   fflush(fp);
118   fclose(fp);
119   silc_free(string);
120 }
121
122 /* Outputs the debug message to stderr. */
123
124 void silc_log_output_debug(char *file, char *function, 
125                            int line, char *string)
126 {
127   /* fprintf(stderr, "%s:%s:%d: %s\n", file, function, line, string); */
128   fprintf(stderr, "%s:%d: %s\n", function, line, string);
129   fflush(stderr);
130   silc_free(string);
131 }
132
133 /* Hexdumps a message */
134
135 void silc_log_output_hexdump(char *file, char *function, 
136                              int line, void *data_in,
137                              unsigned int len, char *string)
138 {
139   int i, k;
140   int off, pos, count;
141   unsigned char *data = (unsigned char *)data_in;
142
143   /* fprintf(stderr, "%s:%s:%d: %s\n", file, function, line, string); */
144   fprintf(stderr, "%s:%d: %s\n", function, line, string);
145   silc_free(string);
146
147   k = 0;
148   off = len % 16;
149   pos = 0;
150   count = 16;
151   while (1) {
152
153     if (off) {
154       if ((len - pos) < 16 && (len - pos <= len - off))
155         count = off;
156     } else {
157       if (pos == len)
158         count = 0;
159     }
160     if (off == len)
161       count = len;
162
163     if (count)
164       fprintf(stderr, "%08X  ", k++ * 16);
165
166     for (i = 0; i < count; i++) {
167       fprintf(stderr, "%02X ", data[pos + i]);
168       
169       if ((i + 1) % 4 == 0)
170         fprintf(stderr, " ");
171     }
172
173     if (count && count < 16) {
174       int j;
175       
176       for (j = 0; j < 16 - count; j++) {
177         fprintf(stderr, "   ");
178
179         if ((j + count + 1) % 4 == 0)
180           fprintf(stderr, " ");
181       }
182     }
183   
184     for (i = 0; i < count; i++) {
185       char ch;
186       
187       if (data[pos] < 32 || data[pos] >= 127)
188         ch = '.';
189       else
190         ch = data[pos];
191
192       fprintf(stderr, "%c", ch);
193       pos++;
194     }
195
196     if (count)
197       fprintf(stderr, "\n");
198
199     if (count < 16)
200       break;
201   }
202 }
203
204 /* Sets log files */
205
206 void silc_log_set_files(char *info, unsigned int info_size, 
207                         char *warning, unsigned int warning_size,
208                         char *error, unsigned int error_size,
209                         char *fatal, unsigned int fatal_size)
210 {
211   log_info_file = info;
212   log_warning_file = warning;
213   log_error_file = error;
214   log_fatal_file = fatal;
215
216   log_info_size = info_size;
217   log_warning_size = warning_size;
218   log_error_size = error_size;
219   log_fatal_size = fatal_size;
220 }