1 /* $NetBSD: log.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
3 /*****************************************************************
5 ** @(#) log.c -- The ZKT error logging module
7 ** Copyright (c) June 2008, Holger Zuleger HZnet. All rights reserved.
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
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 *****************************************************************/
44 # include <sys/types.h>
45 # include <sys/stat.h>
46 # include <sys/time.h>
54 # include "config_zkt.h"
61 /*****************************************************************
62 ** module internal vars & declarations
63 *****************************************************************/
65 static FILE *lg_fpsave
;
66 static int lg_minfilelevel
;
67 static int lg_syslogging
;
68 static int lg_minsyslevel
;
69 static long lg_errcnt
;
70 static const char *lg_progname
;
78 static lg_symtbl_t symtbl
[] = {
79 { LG_NONE
, "none", -1 },
80 { LG_DEBUG
, "debug", LOG_DEBUG
},
81 { LG_INFO
, "info", LOG_INFO
},
82 { LG_NOTICE
, "notice", LOG_NOTICE
},
83 { LG_WARNING
, "warning", LOG_WARNING
},
84 { LG_ERROR
, "error", LOG_ERR
},
85 { LG_FATAL
, "fatal", LOG_CRIT
},
87 { LG_NONE
, "user", LOG_USER
},
88 { LG_NONE
, "daemon", LOG_DAEMON
},
89 { LG_NONE
, "local0", LOG_LOCAL0
},
90 { LG_NONE
, "local1", LOG_LOCAL1
},
91 { LG_NONE
, "local2", LOG_LOCAL2
},
92 { LG_NONE
, "local3", LOG_LOCAL3
},
93 { LG_NONE
, "local4", LOG_LOCAL4
},
94 { LG_NONE
, "local5", LOG_LOCAL5
},
95 { LG_NONE
, "local6", LOG_LOCAL6
},
96 { LG_NONE
, "local7", LOG_LOCAL7
},
100 # define MAXFNAME (1023)
101 /*****************************************************************
102 ** function definitions (for function declarations see log.h)
103 *****************************************************************/
105 /*****************************************************************
106 ** lg_fileopen (path, name) -- open the log file
107 ** Name is a (absolute or relative) file or directory name.
108 ** If path is given and name is a relative path name then path
109 ** is prepended to name.
110 ** returns the open file pointer or NULL on error
111 *****************************************************************/
112 static FILE *lg_fileopen (const char *path
, const char *name
)
118 char fname
[MAXFNAME
+1];
120 if ( name
== NULL
|| *name
== '\0' )
122 else if ( *name
== '/' || path
== NULL
)
123 snprintf (fname
, MAXFNAME
, "%s", name
);
125 snprintf (fname
, MAXFNAME
, "%s/%s", path
, name
);
128 fprintf (stderr
, "\t ==> \"%s\"", fname
);
130 if ( is_directory (fname
) )
132 len
= strlen (fname
);
136 snprintf (fname
+len
, MAXFNAME
-len
, LOG_FNAMETMPL
,
137 t
->tm_year
+ 1900, t
->tm_mon
+1, t
->tm_mday
,
138 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
140 fprintf (stderr
, " isdir \"%s\"", fname
);
145 fprintf (stderr
, "\n");
148 if ( (fp
= fopen (fname
, "a")) == NULL
)
154 /*****************************************************************
155 ** lg_str2lvl (level_name)
156 *****************************************************************/
157 lg_lvl_t
lg_str2lvl (const char *name
)
164 for ( p
= symtbl
; p
->str
; p
++ )
165 if ( strcasecmp (name
, p
->str
) == 0 )
171 /*****************************************************************
172 ** lg_lvl2syslog (level)
173 *****************************************************************/
174 lg_lvl_t
lg_lvl2syslog (lg_lvl_t level
)
178 for ( p
= symtbl
; p
->str
; p
++ )
179 if ( level
== p
->level
)
180 return p
->syslog_level
;
182 assert ( p
->str
!= NULL
); /* we assume not to reach this! */
184 return LOG_DEBUG
; /* if not found, return DEBUG as default */
187 /*****************************************************************
188 ** lg_str2syslog (facility_name)
189 *****************************************************************/
190 int lg_str2syslog (const char *facility
)
194 dbg_val1 ("lg_str2syslog (%s)\n", facility
);
198 for ( p
= symtbl
; p
->str
; p
++ )
199 if ( strcasecmp (facility
, p
->str
) == 0 )
200 return p
->syslog_level
;
205 /*****************************************************************
206 ** lg_lvl2str (level)
207 *****************************************************************/
208 const char *lg_lvl2str (lg_lvl_t level
)
212 if ( level
< LG_DEBUG
)
215 for ( p
= symtbl
; p
->str
; p
++ )
216 if ( level
== p
->level
)
221 /*****************************************************************
222 ** lg_geterrcnt () -- returns the current value of the internal
224 *****************************************************************/
230 /*****************************************************************
231 ** lg_seterrcnt () -- sets the internal error counter
232 ** returns the current value
233 *****************************************************************/
234 long lg_seterrcnt (long value
)
236 return lg_errcnt
= value
;
239 /*****************************************************************
240 ** lg_reseterrcnt () -- resets the internal error counter to 0
241 ** returns the current value
242 *****************************************************************/
243 long lg_reseterrcnt ()
245 return lg_seterrcnt (0L);
249 /*****************************************************************
250 ** lg_open (prog, facility, syslevel, path, file, filelevel)
251 ** -- open the log channel
254 ** -1 on file open error
255 *****************************************************************/
256 int lg_open (const char *progname
, const char *facility
, const char *syslevel
, const char *path
, const char *file
, const char *filelevel
)
260 dbg_val6 ("lg_open (%s, %s, %s, %s, %s, %s)\n", progname
, facility
, syslevel
, path
, file
, filelevel
);
262 lg_minsyslevel
= lg_str2lvl (syslevel
);
263 lg_minfilelevel
= lg_str2lvl (filelevel
);
265 sysfacility
= lg_str2syslog (facility
);
266 if ( sysfacility
>= 0 )
269 dbg_val2 ("lg_open: openlog (%s, LOG_NDELAY, %d)\n", progname
, lg_str2syslog (facility
));
270 openlog (progname
, LOG_NDELAY
, lg_str2syslog (facility
));
272 if ( file
&& * file
)
274 if ( (lg_fp
= lg_fileopen (path
, file
)) == NULL
)
276 lg_progname
= progname
;
282 /*****************************************************************
283 ** lg_close () -- close the open filepointer for error logging
284 ** return 0 if no error log file is currently open,
285 ** otherwise the return code of fclose is returned.
286 *****************************************************************/
298 ret
= fclose (lg_fp
);
305 /*****************************************************************
306 ** lg_zone_start (domain)
307 ** -- reopen the log channel
310 ** -1 on file open error
311 *****************************************************************/
312 int lg_zone_start (const char *dir
, const char *domain
)
316 dbg_val2 ("lg_zone_start (%s, %s)\n", dir
, domain
);
318 snprintf (fname
, sizeof (fname
), LOG_DOMAINTMPL
, domain
);
321 lg_fp
= lg_fileopen (dir
, fname
);
323 return lg_fp
!= NULL
;
326 /*****************************************************************
327 ** lg_zone_end (domain)
328 ** -- close the (reopened) log channel
331 ** -1 on file open error
332 *****************************************************************/
335 if ( lg_fp
&& lg_fpsave
)
346 /*****************************************************************
348 ** lg_args (level, argc, argv[])
349 ** log all command line arguments (up to a length of 511 chars)
350 ** with priority level
352 *****************************************************************/
353 void lg_args (lg_lvl_t level
, int argc
, char * const argv
[])
360 for ( i
= 0; i
< argc
&& len
< sizeof (cmdline
); i
++ )
361 len
+= snprintf (cmdline
+len
, sizeof (cmdline
) - len
, " %s", argv
[i
]);
364 lg_mesg (level
, "------------------------------------------------------------");
368 lg_mesg (level
, "running%s ", cmdline
);
371 /*****************************************************************
373 ** lg_mesg (level, fmt, ...)
375 ** Write a given message to the error log file and counts
376 ** all messages written with an level greater than LOG_ERR.
378 ** All messages will be on one line in the logfile, so it's
379 ** not necessary to add an '\n' to the message.
381 ** To call this function before an elog_open() is called is
384 *****************************************************************/
385 void lg_mesg (int priority
, char *fmt
, ...)
392 assert (fmt
!= NULL
);
393 assert (priority
>= LG_DEBUG
&& priority
<= LG_FATAL
);
397 dbg_val3 ("syslog = %d prio = %d >= sysmin = %d\n", lg_syslogging
, priority
, lg_minsyslevel
);
398 if ( lg_syslogging
&& priority
>= lg_minsyslevel
)
400 #if defined (LOG_WITH_LEVEL) && LOG_WITH_LEVEL
401 snprintf (format
, sizeof (format
), "%s: %s", lg_lvl2str(priority
), fmt
);
405 vsyslog (lg_lvl2syslog (priority
), fmt
, ap
);
409 dbg_val3 ("filelg = %d prio = %d >= filmin = %d\n", lg_fp
!=NULL
, priority
, lg_minfilelevel
);
410 if ( lg_fp
&& priority
>= lg_minfilelevel
)
412 #if defined (LOG_WITH_TIMESTAMP) && LOG_WITH_TIMESTAMP
413 gettimeofday (&tv
, NULL
);
414 t
= localtime ((time_t *) &tv
.tv_sec
);
415 fprintf (lg_fp
, "%04d-%02d-%02d ",
416 t
->tm_year
+1900, t
->tm_mon
+1, t
->tm_mday
);
417 fprintf (lg_fp
, "%02d:%02d:%02d.%03ld: ",
418 t
->tm_hour
, t
->tm_min
, t
->tm_sec
, tv
.tv_usec
/ 1000);
420 #if defined (LOG_WITH_PROGNAME) && LOG_WITH_PROGNAME
422 fprintf (lg_fp
, "%s: ", lg_progname
);
424 #if defined (LOG_WITH_LEVEL) && LOG_WITH_LEVEL
425 if ( fmt
!= format
) /* level is not in fmt string */
426 fprintf (lg_fp
, "%s: ", lg_lvl2str(priority
));
429 vfprintf (lg_fp
, fmt
, ap
);
431 fprintf (lg_fp
, "\n");
434 if ( priority
>= LG_ERROR
)
440 const char *progname
;
441 int main (int argc
, char *argv
[])
443 const char *levelstr
;
444 const char *newlevelstr
;
455 level
= lg_str2lvl (levelstr
);
456 newlevelstr
= lg_lvl2str (level
+1);
457 dbg_val4 ("base level = %s(%d) newlevel = %s(%d)\n", levelstr
, level
, newlevelstr
, level
+1);
458 if ( (err
= lg_open (progname
,
471 fprintf (stderr
, "\topen error %d\n", err
);
474 lg_mesg (LG_DEBUG
, "debug message");
475 lg_mesg (LG_INFO
, "INFO message");
476 lg_mesg (LG_NOTICE
, "Notice message");
477 lg_mesg (LG_WARNING
, "Warning message");
478 lg_mesg (LG_ERROR
, "Error message");
479 lg_mesg (LG_FATAL
, "Fatal message ");
482 if ( (err
= lg_close ()) < 0 )
483 fprintf (stderr
, "\tclose error %d\n", err
);