Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / contrib / zkt / log.c
blobd8647936d9cf1119ed6353438a017b5241a38161
1 /* $NetBSD$ */
3 /*****************************************************************
4 **
5 ** @(#) log.c -- The ZKT error logging module
6 **
7 ** Copyright (c) June 2008, Holger Zuleger HZnet. All rights reserved.
8 **
9 ** This software is open source.
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
13 ** are met:
15 ** Redistributions of source code must retain the above copyright notice,
16 ** this list of conditions and the following disclaimer.
18 ** Redistributions in binary form must reproduce the above copyright notice,
19 ** this list of conditions and the following disclaimer in the documentation
20 ** and/or other materials provided with the distribution.
22 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
23 ** be used to endorse or promote products derived from this software without
24 ** specific prior written permission.
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 ** POSSIBILITY OF SUCH DAMAGE.
39 *****************************************************************/
40 # include <stdio.h>
41 # include <string.h>
42 # include <stdlib.h>
43 # include <ctype.h>
44 # include <sys/types.h>
45 # include <sys/stat.h>
46 # include <sys/time.h>
47 # include <time.h>
48 # include <assert.h>
49 # include <errno.h>
50 # include <syslog.h>
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 # include "config_zkt.h"
55 # include "misc.h"
56 # include "debug.h"
57 #define extern
58 # include "log.h"
59 #undef extern
61 /*****************************************************************
62 ** module internal vars & declarations
63 *****************************************************************/
64 static FILE *lg_fp;
65 static int lg_minfilelevel;
66 static int lg_syslogging;
67 static int lg_minsyslevel;
68 static long lg_errcnt;
69 static const char *lg_progname;
71 typedef struct {
72 lg_lvl_t level;
73 const char *str;
74 int syslog_level;
75 } lg_symtbl_t;
77 static lg_symtbl_t symtbl[] = {
78 { LG_NONE, "none", -1 },
79 { LG_DEBUG, "debug", LOG_DEBUG },
80 { LG_INFO, "info", LOG_INFO },
81 { LG_NOTICE, "notice", LOG_NOTICE },
82 { LG_WARNING, "warning", LOG_WARNING },
83 { LG_ERROR, "error", LOG_ERR },
84 { LG_FATAL, "fatal", LOG_CRIT },
86 { LG_NONE, "user", LOG_USER },
87 { LG_NONE, "daemon", LOG_DAEMON },
88 { LG_NONE, "local0", LOG_LOCAL0 },
89 { LG_NONE, "local1", LOG_LOCAL1 },
90 { LG_NONE, "local2", LOG_LOCAL2 },
91 { LG_NONE, "local3", LOG_LOCAL3 },
92 { LG_NONE, "local4", LOG_LOCAL4 },
93 { LG_NONE, "local5", LOG_LOCAL5 },
94 { LG_NONE, "local6", LOG_LOCAL6 },
95 { LG_NONE, "local7", LOG_LOCAL7 },
96 { LG_NONE, NULL, -1 }
99 # define MAXFNAME (1023)
100 /*****************************************************************
101 ** function definitions (for function declarations see log.h)
102 *****************************************************************/
104 /*****************************************************************
105 ** lg_fileopen (path, name) -- open the log file
106 ** Name is a (absolute or relative) file or directory name.
107 ** If path is given and name is a relative path name then path
108 ** is prepended to name.
109 ** returns the open file pointer or NULL on error
110 *****************************************************************/
111 static FILE *lg_fileopen (const char *path, const char *name)
113 int len;
114 FILE *fp;
115 struct tm *t;
116 time_t sec;
117 char fname[MAXFNAME+1];
119 if ( name == NULL || *name == '\0' )
120 return NULL;
121 else if ( *name == '/' || path == NULL )
122 snprintf (fname, MAXFNAME, "%s", name);
123 else
124 snprintf (fname, MAXFNAME, "%s/%s", path, name);
126 # ifdef LOG_TEST
127 fprintf (stderr, "\t ==> \"%s\"", fname);
128 # endif
129 if ( is_directory (fname) )
131 len = strlen (fname);
133 time (&sec);
134 t = gmtime (&sec);
135 snprintf (fname+len, MAXFNAME-len, LOG_FNAMETMPL,
136 t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
137 t->tm_hour, t->tm_min, t->tm_sec);
138 # ifdef LOG_TEST
139 fprintf (stderr, " isdir \"%s\"", fname);
140 # endif
143 # ifdef LOG_TEST
144 fprintf (stderr, "\n");
145 # endif
147 if ( (fp = fopen (fname, "a")) == NULL )
148 return NULL;
150 return fp;
153 /*****************************************************************
154 ** lg_str2lvl (level_name)
155 *****************************************************************/
156 lg_lvl_t lg_str2lvl (const char *name)
158 lg_symtbl_t *p;
160 if ( !name )
161 return LG_NONE;
163 for ( p = symtbl; p->str; p++ )
164 if ( strcasecmp (name, p->str) == 0 )
165 return p->level;
167 return LG_NONE;
170 /*****************************************************************
171 ** lg_lvl2syslog (level)
172 *****************************************************************/
173 lg_lvl_t lg_lvl2syslog (lg_lvl_t level)
175 lg_symtbl_t *p;
177 for ( p = symtbl; p->str; p++ )
178 if ( level == p->level )
179 return p->syslog_level;
181 assert ( p->str != NULL ); /* we assume not to reach this! */
183 return LOG_DEBUG; /* if not found, return DEBUG as default */
186 /*****************************************************************
187 ** lg_str2syslog (facility_name)
188 *****************************************************************/
189 int lg_str2syslog (const char *facility)
191 lg_symtbl_t *p;
193 dbg_val1 ("lg_str2syslog (%s)\n", facility);
194 if ( !facility )
195 return LG_NONE;
197 for ( p = symtbl; p->str; p++ )
198 if ( strcasecmp (facility, p->str) == 0 )
199 return p->syslog_level;
201 return LG_NONE;
204 /*****************************************************************
205 ** lg_lvl2str (level)
206 *****************************************************************/
207 const char *lg_lvl2str (lg_lvl_t level)
209 lg_symtbl_t *p;
211 if ( level < LG_DEBUG )
212 return "none";
214 for ( p = symtbl; p->str; p++ )
215 if ( level == p->level )
216 return p->str;
217 return "fatal";
220 /*****************************************************************
221 ** lg_geterrcnt () -- returns the current value of the internal
222 ** error counter
223 *****************************************************************/
224 long lg_geterrcnt ()
226 return lg_errcnt;
229 /*****************************************************************
230 ** lg_seterrcnt () -- sets the internal error counter
231 ** returns the current value
232 *****************************************************************/
233 long lg_seterrcnt (long value)
235 return lg_errcnt = value;
238 /*****************************************************************
239 ** lg_reseterrcnt () -- resets the internal error counter to 0
240 ** returns the current value
241 *****************************************************************/
242 long lg_reseterrcnt ()
244 return lg_seterrcnt (0L);
248 /*****************************************************************
249 ** lg_open (prog, facility, syslevel, path, file, filelevel)
250 ** -- open the log channel
251 ** return values:
252 ** 0 on success
253 ** -1 on file open error
254 *****************************************************************/
255 int lg_open (const char *progname, const char *facility, const char *syslevel, const char *path, const char *file, const char *filelevel)
257 int sysfacility;
259 dbg_val6 ("lg_open (%s, %s, %s, %s, %s, %s)\n", progname, facility, syslevel, path, file, filelevel);
261 lg_minsyslevel = lg_str2lvl (syslevel);
262 lg_minfilelevel = lg_str2lvl (filelevel);
264 sysfacility = lg_str2syslog (facility);
265 if ( sysfacility >= 0 )
267 lg_syslogging = 1;
268 dbg_val2 ("lg_open: openlog (%s, LOG_NDELAY, %d)\n", progname, lg_str2syslog (facility));
269 openlog (progname, LOG_NDELAY, lg_str2syslog (facility));
271 if ( file && * file )
273 if ( (lg_fp = lg_fileopen (path, file)) == NULL )
274 return -1;
275 lg_progname = progname;
278 return 0;
281 /*****************************************************************
282 ** lg_close () -- close the open filepointer for error logging
283 ** return 0 if no error log file is currently open,
284 ** otherwise the return code of fclose is returned.
285 *****************************************************************/
286 int lg_close ()
288 int ret = 0;
290 if ( lg_syslogging )
292 closelog ();
293 lg_syslogging = 0;
295 if ( lg_fp )
297 ret = fclose (lg_fp);
298 lg_fp = NULL;
301 return ret;
304 /*****************************************************************
306 ** lg_args (level, argc, argv[])
307 ** log all command line arguments (up to a length of 511 chars)
308 ** with priority level
310 *****************************************************************/
311 void lg_args (lg_lvl_t level, int argc, char * const argv[])
313 char cmdline[511+1];
314 int len;
315 int i;
317 len = 0;
318 for ( i = 0; i < argc && len < sizeof (cmdline); i++ )
319 len += snprintf (cmdline+len, sizeof (cmdline) - len, " %s", argv[i]);
321 #if 1
322 lg_mesg (level, "------------------------------------------------------------");
323 #else
324 lg_mesg (level, "");
325 #endif
326 lg_mesg (level, "running%s ", cmdline);
329 /*****************************************************************
331 ** lg_mesg (level, fmt, ...)
333 ** Write a given message to the error log file and counts
334 ** all messages written with an level greater than LOG_ERR.
336 ** All messages will be on one line in the logfile, so it's
337 ** not necessary to add an '\n' to the message.
339 ** To call this function before an elog_open() is called is
340 ** useless!
342 *****************************************************************/
343 void lg_mesg (int priority, char *fmt, ...)
345 va_list ap;
346 struct timeval tv;
347 struct tm *t;
348 char format[256];
350 assert (fmt != NULL);
351 assert (priority >= LG_DEBUG && priority <= LG_FATAL);
353 format[0] ='\0';
355 dbg_val3 ("syslog = %d prio = %d >= sysmin = %d\n", lg_syslogging, priority, lg_minsyslevel);
356 if ( lg_syslogging && priority >= lg_minsyslevel )
358 #if defined (LOG_WITH_LEVEL) && LOG_WITH_LEVEL
359 snprintf (format, sizeof (format), "%s: %s", lg_lvl2str(priority), fmt);
360 fmt = format;
361 #endif
362 va_start(ap, fmt);
363 vsyslog (lg_lvl2syslog (priority), fmt, ap);
364 va_end(ap);
367 dbg_val3 ("filelg = %d prio = %d >= filmin = %d\n", lg_fp!=NULL, priority, lg_minfilelevel);
368 if ( lg_fp && priority >= lg_minfilelevel )
370 #if defined (LOG_WITH_TIMESTAMP) && LOG_WITH_TIMESTAMP
371 gettimeofday (&tv, NULL);
372 t = localtime ((time_t *) &tv.tv_sec);
373 fprintf (lg_fp, "%04d-%02d-%02d ",
374 t->tm_year+1900, t->tm_mon+1, t->tm_mday);
375 fprintf (lg_fp, "%02d:%02d:%02d.%03ld: ",
376 t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
377 #endif
378 #if defined (LOG_WITH_PROGNAME) && LOG_WITH_PROGNAME
379 if ( lg_progname )
380 fprintf (lg_fp, "%s: ", lg_progname);
381 #endif
382 #if defined (LOG_WITH_LEVEL) && LOG_WITH_LEVEL
383 if ( fmt != format ) /* level is not in fmt string */
384 fprintf (lg_fp, "%s: ", lg_lvl2str(priority));
385 #endif
386 va_start(ap, fmt);
387 vfprintf (lg_fp, fmt, ap);
388 va_end(ap);
389 fprintf (lg_fp, "\n");
392 if ( priority >= LG_ERROR )
393 lg_errcnt++;
397 #ifdef LOG_TEST
398 const char *progname;
399 int main (int argc, char *argv[])
401 const char *levelstr;
402 const char *newlevelstr;
403 int level;
404 int err;
406 progname = *argv;
408 if ( --argc )
409 levelstr = *++argv;
410 else
411 levelstr = "fatal";
413 level = lg_str2lvl (levelstr);
414 newlevelstr = lg_lvl2str (level+1);
415 dbg_val4 ("base level = %s(%d) newlevel = %s(%d)\n", levelstr, level, newlevelstr, level+1);
416 if ( (err = lg_open (progname,
417 #if 1
418 "user",
419 #else
420 "none",
421 #endif
422 levelstr, ".",
423 #if 1
424 "test.log",
425 #else
426 NULL,
427 #endif
428 newlevelstr)) )
429 fprintf (stderr, "\topen error %d\n", err);
430 else
432 lg_mesg (LG_DEBUG, "debug message");
433 lg_mesg (LG_INFO, "INFO message");
434 lg_mesg (LG_NOTICE, "Notice message");
435 lg_mesg (LG_WARNING, "Warning message");
436 lg_mesg (LG_ERROR, "Error message");
437 lg_mesg (LG_FATAL, "Fatal message ");
440 if ( (err = lg_close ()) < 0 )
441 fprintf (stderr, "\tclose error %d\n", err);
443 return 0;
445 #endif