Add OID-database entries for the MARC, BIB-2 and ZeeRex attribute sets.
[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.28 2002-08-29 09:58:42 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 static char l_prefix2[512] = "";
42
43 static struct {
44     int mask;
45     char *name;
46 } mask_names[] =
47 {
48     { LOG_FATAL, "fatal"},
49     { LOG_DEBUG, "debug"},
50     { LOG_WARN,  "warn" },
51     { LOG_LOG,   "log"  },
52     { LOG_ERRNO, ""},
53     { LOG_MALLOC, "malloc"},
54     { LOG_ALL,   "all"  },
55     { 0,         "none" },
56     { 0, NULL }
57 };  
58
59 FILE *yaz_log_file(void)
60 {
61     if (!l_file)
62         l_file = stderr;
63     return l_file;
64 }
65
66 void yaz_log_init_file (const char *fname)
67 {
68     FILE *new_file;
69     if (!l_file)
70         l_file = stderr;
71     if (!fname || !*fname)
72         return;
73     if (!(new_file = fopen(fname, "a")))
74         return;
75     if (l_file != stderr)
76     {
77         fclose (l_file);
78     }
79     setvbuf(new_file, 0, _IONBF, 0);
80     l_file = new_file;
81 }
82
83 void yaz_log_init_level (int level)
84 {
85     l_level = level;
86 }
87
88 void yaz_log_init_prefix (const char *prefix)
89 {
90     if (prefix && *prefix)
91         sprintf(l_prefix, "%.511s ", prefix);
92     else
93         *l_prefix = 0;
94 }
95
96 void yaz_log_init_prefix2 (const char *prefix)
97 {
98     if (prefix && *prefix)
99         sprintf(l_prefix2, "%.511s ", prefix);
100     else
101         *l_prefix2 = 0;
102 }
103
104 void yaz_log_init(int level, const char *prefix, const char *fname)
105 {
106     yaz_log_init_level (level);
107     yaz_log_init_prefix (prefix);
108     yaz_log_init_file (fname);
109 }
110
111 static void (*start_hook_func)(int, const char *, void *) = NULL;
112 static void *start_hook_info;
113 static void (*end_hook_func)(int, const char *, void *) = NULL;
114 static void *end_hook_info;
115
116 void log_event_start (void (*func)(int, const char *, void *), void *info)
117 {
118     start_hook_func = func;
119     start_hook_info = info;
120 }
121
122 void log_event_end (void (*func)(int, const char *, void *), void *info)
123 {
124     end_hook_func = func;
125     end_hook_info = info;
126 }
127
128 void yaz_log(int level, const char *fmt, ...)
129 {
130     va_list ap;
131     char buf[4096], flags[1024];
132     int i;
133     time_t ti;
134     struct tm *tim;
135     char tbuf[50];
136     int o_level = level;
137
138     if (!(level & l_level))
139         return;
140     if (!l_file)
141         l_file = stderr;
142     *flags = '\0';
143     for (i = 0; level && mask_names[i].name; i++)
144         if (mask_names[i].mask & level)
145         {
146             if (*mask_names[i].name)
147                 sprintf(flags + strlen(flags), "[%s]", mask_names[i].name);
148             level -= mask_names[i].mask;
149         }
150     va_start(ap, fmt);
151 #ifdef WIN32
152     _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
153 #else
154 /* !WIN32 */
155 #if HAVE_VSNPRINTF
156     vsnprintf(buf, sizeof(buf), fmt, ap);
157 #else
158     vsprintf(buf, fmt, ap);
159 #endif
160 #endif
161 /* WIN32 */
162     if (o_level & LOG_ERRNO)
163     {
164 #ifdef WIN32
165         DWORD err = GetLastError();
166         if (err)
167         {
168             strcat(buf, " [");
169             FormatMessage(
170                 FORMAT_MESSAGE_FROM_SYSTEM,
171                 NULL,
172                 err,
173                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
174                 (LPTSTR) buf + strlen(buf),
175                 2048,
176                 NULL);
177             strcat(buf, "]");
178         }
179 #else
180         sprintf(buf + strlen(buf), " [%s]", strerror(errno));
181 #endif
182     }
183     if (start_hook_func)
184         (*start_hook_func)(o_level, buf, start_hook_info);
185     ti = time(0);
186     tim = localtime(&ti);
187     strftime(tbuf, 50, "%H:%M:%S-%d/%m", tim);
188     fprintf(l_file, "%s: %s%s %s%s\n", tbuf, l_prefix, flags,
189             l_prefix2, buf);
190     fflush(l_file);
191     if (end_hook_func)
192         (*end_hook_func)(o_level, buf, end_hook_info);
193 }
194
195 int yaz_log_mask_str (const char *str)
196 {
197     return yaz_log_mask_str_x (str, LOG_DEFAULT_LEVEL);
198 }
199
200 int yaz_log_mask_str_x (const char *str, int level)
201 {
202     const char *p;
203     int i;
204
205     while (*str)
206     {
207         for (p = str; *p && *p != ','; p++)
208             ;
209         if (*str == '-' || isdigit(*str))
210             level = atoi (str);
211         else
212             for (i = 0; mask_names[i].name; i++)
213                 if (strlen (mask_names[i].name) == (size_t) (p-str) &&
214                     memcmp (mask_names[i].name, str, p-str) == 0)
215                 {
216                     if (mask_names[i].mask)
217                         level |= mask_names[i].mask;
218                     else
219                         level = 0;
220                 }
221         if (*p == ',')
222             p++;
223         str = p;
224     }
225     return level;
226 }