Fix warnings
[yaz-moved-to-github.git] / util / log.c
1 /*
2  * Copyright (c) 1995-2002, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: log.c,v 1.27 2002-06-18 21:30:39 adam Exp $
6  */
7
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #ifdef WIN32
13 #include <windows.h>
14 #endif
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ctype.h>
19 #include <string.h>
20 #include <stdarg.h>
21 #include <errno.h>
22 #include <time.h>
23 #include <yaz/log.h>
24
25 #define HAS_STRERROR 1
26
27 #if HAS_STRERROR
28
29 #else
30 char *strerror(int n)
31 {
32         extern char *sys_errlist[];
33         return sys_errlist[n];
34 }
35
36 #endif
37
38 static int l_level = LOG_DEFAULT_LEVEL;
39 static FILE *l_file = NULL;
40 static char l_prefix[512] = "";
41
42 static struct {
43     int mask;
44     char *name;
45 } mask_names[] =
46 {
47     { LOG_FATAL, "fatal"},
48     { LOG_DEBUG, "debug"},
49     { LOG_WARN,  "warn" },
50     { LOG_LOG,   "log"  },
51     { LOG_ERRNO, ""},
52     { LOG_MALLOC, "malloc"},
53     { LOG_ALL,   "all"  },
54     { 0,         "none" },
55     { 0, NULL }
56 };  
57
58 FILE *yaz_log_file(void)
59 {
60     if (!l_file)
61         l_file = stderr;
62     return l_file;
63 }
64
65 void yaz_log_init_file (const char *fname)
66 {
67     FILE *new_file;
68     if (!l_file)
69         l_file = stderr;
70     if (!fname || !*fname)
71         return;
72     if (!(new_file = fopen(fname, "a")))
73         return;
74     if (l_file != stderr)
75     {
76         fclose (l_file);
77     }
78     setvbuf(new_file, 0, _IONBF, 0);
79     l_file = new_file;
80 }
81
82 void yaz_log_init_level (int level)
83 {
84     l_level = level;
85 }
86
87 void yaz_log_init_prefix (const char *prefix)
88 {
89     if (prefix && *prefix)
90         sprintf(l_prefix, "%.511s ", prefix);
91     else
92         *l_prefix = 0;
93 }
94
95 void yaz_log_init(int level, const char *prefix, const char *fname)
96 {
97     yaz_log_init_level (level);
98     yaz_log_init_prefix (prefix);
99     yaz_log_init_file (fname);
100 }
101
102 static void (*start_hook_func)(int, const char *, void *) = NULL;
103 static void *start_hook_info;
104 static void (*end_hook_func)(int, const char *, void *) = NULL;
105 static void *end_hook_info;
106
107 void log_event_start (void (*func)(int, const char *, void *), void *info)
108 {
109     start_hook_func = func;
110     start_hook_info = info;
111 }
112
113 void log_event_end (void (*func)(int, const char *, void *), void *info)
114 {
115     end_hook_func = func;
116     end_hook_info = info;
117 }
118
119 void yaz_log(int level, const char *fmt, ...)
120 {
121     va_list ap;
122     char buf[4096], flags[1024];
123     int i;
124     time_t ti;
125     struct tm *tim;
126     char tbuf[50];
127     int o_level = level;
128
129     if (!(level & l_level))
130         return;
131     if (!l_file)
132         l_file = stderr;
133     *flags = '\0';
134     for (i = 0; level && mask_names[i].name; i++)
135         if (mask_names[i].mask & level)
136         {
137             if (*mask_names[i].name)
138                 sprintf(flags + strlen(flags), "[%s]", mask_names[i].name);
139             level -= mask_names[i].mask;
140         }
141     va_start(ap, fmt);
142 #ifdef WIN32
143     _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
144 #else
145 /* !WIN32 */
146 #if HAVE_VSNPRINTF
147     vsnprintf(buf, sizeof(buf), fmt, ap);
148 #else
149     vsprintf(buf, fmt, ap);
150 #endif
151 #endif
152 /* WIN32 */
153     if (o_level & LOG_ERRNO)
154     {
155 #ifdef WIN32
156         DWORD err = GetLastError();
157         if (err)
158         {
159             strcat(buf, " [");
160             FormatMessage(
161                 FORMAT_MESSAGE_FROM_SYSTEM,
162                 NULL,
163                 err,
164                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
165                 (LPTSTR) buf + strlen(buf),
166                 2048,
167                 NULL);
168             strcat(buf, "]");
169         }
170 #else
171         sprintf(buf + strlen(buf), " [%s]", strerror(errno));
172 #endif
173     }
174     if (start_hook_func)
175         (*start_hook_func)(o_level, buf, start_hook_info);
176     ti = time(0);
177     tim = localtime(&ti);
178     strftime(tbuf, 50, "%H:%M:%S-%d/%m", tim);
179     fprintf(l_file, "%s: %s%s %s\n", tbuf, l_prefix, flags, buf);
180     fflush(l_file);
181     if (end_hook_func)
182         (*end_hook_func)(o_level, buf, end_hook_info);
183 }
184
185 int yaz_log_mask_str (const char *str)
186 {
187     return yaz_log_mask_str_x (str, LOG_DEFAULT_LEVEL);
188 }
189
190 int yaz_log_mask_str_x (const char *str, int level)
191 {
192     const char *p;
193     int i;
194
195     while (*str)
196     {
197         for (p = str; *p && *p != ','; p++)
198             ;
199         if (*str == '-' || isdigit(*str))
200             level = atoi (str);
201         else
202             for (i = 0; mask_names[i].name; i++)
203                 if (strlen (mask_names[i].name) == (size_t) (p-str) &&
204                     memcmp (mask_names[i].name, str, p-str) == 0)
205                 {
206                     if (mask_names[i].mask)
207                         level |= mask_names[i].mask;
208                     else
209                         level = 0;
210                 }
211         if (*p == ',')
212             p++;
213         str = p;
214     }
215     return level;
216 }