OpenDNSSEC-signer  1.3.15
log.c
Go to the documentation of this file.
1 /*
2  * $Id: log.c 3845 2010-08-31 14:19:24Z matthijs $
3  *
4  * Copyright (c) 2009 NLnet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "shared/duration.h"
36 #include "shared/file.h"
37 #include "shared/log.h"
38 #include "shared/util.h"
39 
40 #include <stdarg.h> /* va_start(), va_end() */
41 #include <stdio.h> /* fflush, fprintf(), vsnprintf() */
42 #include <stdlib.h> /* exit() */
43 #include <string.h> /* strlen() */
44 
45 #ifdef HAVE_SYSLOG_H
46 #include <strings.h> /* strncasecmp() */
47 #include <syslog.h> /* openlog(), closelog(), syslog() */
48 static int logging_to_syslog = 0;
49 #else /* !HAVE_SYSLOG_H */
50 #define LOG_EMERG 0 /* ods_fatal_exit */
51 #define LOG_ALERT 1 /* ods_log_alert */
52 #define LOG_CRIT 2 /* ods_log_crit */
53 #define LOG_ERR 3 /* ods_log_error */
54 #define LOG_WARNING 4 /* ods_log_warning */
55 #define LOG_NOTICE 5 /* ods_log_info */
56 #define LOG_INFO 6 /* ods_log_verbose */
57 #define LOG_DEBUG 7 /* ods_log_debug */
58 #endif /* HAVE_SYSLOG_H */
59 
60 #define LOG_DEEEBUG 8 /* ods_log_deeebug */
61 
62 static FILE* logfile = NULL;
63 static int log_level = LOG_CRIT;
64 
65 #define CTIME_LENGTH 26
66 
72 #if defined(HAVE_SYSLOG_R) && defined(HAVE_OPENLOG_R) && defined(HAVE_CLOSELOG_R)
73 struct syslog_data sdata = SYSLOG_DATA_INIT;
74 #else
75 #undef HAVE_SYSLOG_R
76 #undef HAVE_OPENLOG_R
77 #undef HAVE_CLOSELOG_R
78 #endif
79 
80 /* TODO:
81  - log_init should have program_name variable
82  - wrap special case logging onto generic one
83  - check if xml-specific logging functions are still neeeded (enforcer)
84  -
85 */
86 
87 #define MY_PACKAGE_TARNAME "ods-signerd"
88 
89 static const char* log_str = "log";
90 
95 void
96 ods_log_init(const char *filename, int use_syslog, int verbosity)
97 {
98 #ifdef HAVE_SYSLOG_H
99  int facility;
100 #endif /* HAVE_SYSLOG_H */
101  ods_log_verbose("[%s] switching log to %s verbosity %i (log level %i)",
102  log_str, use_syslog?"syslog":(filename&&filename[0]?filename:"stderr"),
103  verbosity, verbosity+2);
104  if (logfile && logfile != stderr) {
105  ods_fclose(logfile);
106  }
107  log_level = verbosity + 2;
108 
109 #ifdef HAVE_SYSLOG_H
110  if(logging_to_syslog) {
111 #ifdef HAVE_CLOSELOG_R
112  closelog_r(&sdata);
113 #else
114  closelog();
115 #endif
116  logging_to_syslog = 0;
117  }
118  if(use_syslog) {
119  facility = ods_log_get_facility(filename);
120 #ifdef HAVE_OPENLOG_R
121  openlog_r(MY_PACKAGE_TARNAME, LOG_NDELAY, facility, &sdata);
122 #else
123  openlog(MY_PACKAGE_TARNAME, LOG_NDELAY, facility);
124 #endif
125  logging_to_syslog = 1;
126  return;
127  }
128 #endif /* HAVE_SYSLOG_H */
129 
130  if(filename && filename[0]) {
131  logfile = ods_fopen(filename, NULL, "a");
132  if (logfile) {
133  ods_log_debug("[%s] new logfile %s", log_str, filename);
134  return;
135  }
136  logfile = stderr;
137  ods_log_warning("[%s] cannot open %s for appending, logging to "
138  "stderr", log_str, filename);
139  } else {
140  logfile = stderr;
141  }
142  return;
143 }
144 
145 
150 void
152 {
153  ods_log_debug("[%s] close log", log_str);
154  ods_log_init(NULL, 0, 0);
155 }
156 
157 
165 #ifdef HAVE_SYSLOG_H
166 int
167 ods_log_get_facility(const char* facility)
168 {
169  int length;
170 
171  if (!facility) {
172  return LOG_DAEMON;
173  }
174  length = strlen(facility);
175 
176  if (length == 4 && strncasecmp(facility, "KERN", 4) == 0)
177  return LOG_KERN;
178  else if (length == 4 && strncasecmp(facility, "USER", 4) == 0)
179  return LOG_USER;
180  else if (length == 4 && strncasecmp(facility, "MAIL", 4) == 0)
181  return LOG_MAIL;
182  else if (length == 6 && strncasecmp(facility, "DAEMON", 6) == 0)
183  return LOG_DAEMON;
184  else if (length == 4 && strncasecmp(facility, "AUTH", 4) == 0)
185  return LOG_AUTH;
186  else if (length == 3 && strncasecmp(facility, "LPR", 3) == 0)
187  return LOG_LPR;
188  else if (length == 4 && strncasecmp(facility, "NEWS", 4) == 0)
189  return LOG_NEWS;
190  else if (length == 4 && strncasecmp(facility, "UUCP", 4) == 0)
191  return LOG_UUCP;
192  else if (length == 4 && strncasecmp(facility, "CRON", 4) == 0)
193  return LOG_CRON;
194  else if (length == 6 && strncasecmp(facility, "LOCAL0", 6) == 0)
195  return LOG_LOCAL0;
196  else if (length == 6 && strncasecmp(facility, "LOCAL1", 6) == 0)
197  return LOG_LOCAL1;
198  else if (length == 6 && strncasecmp(facility, "LOCAL2", 6) == 0)
199  return LOG_LOCAL2;
200  else if (length == 6 && strncasecmp(facility, "LOCAL3", 6) == 0)
201  return LOG_LOCAL3;
202  else if (length == 6 && strncasecmp(facility, "LOCAL4", 6) == 0)
203  return LOG_LOCAL4;
204  else if (length == 6 && strncasecmp(facility, "LOCAL5", 6) == 0)
205  return LOG_LOCAL5;
206  else if (length == 6 && strncasecmp(facility, "LOCAL6", 6) == 0)
207  return LOG_LOCAL6;
208  else if (length == 6 && strncasecmp(facility, "LOCAL7", 6) == 0)
209  return LOG_LOCAL7;
210  ods_log_warning("[%s] syslog facility %s not supported, logging to "
211  "log_daemon", log_str, facility);
212  return LOG_DAEMON;
213 
214 }
215 #endif /* HAVE_SYSLOG_H */
216 
221 int
223 {
224  return log_level;
225 }
226 
231 static void
232 ods_log_vmsg(int priority, const char* t, const char* s, va_list args)
233 {
234  char message[ODS_SE_MAXLINE];
235  static char nowstr[CTIME_LENGTH];
236  time_t now = time_now();
237 
238  vsnprintf(message, sizeof(message), s, args);
239 
240 #ifdef HAVE_SYSLOG_H
241  if (logging_to_syslog) {
242 #ifdef HAVE_SYSLOG_R
243  syslog_r(priority, &sdata, "%s", message);
244 #else
245  syslog(priority, "%s", message);
246 #endif
247  return;
248  }
249 #endif /* HAVE_SYSLOG_H */
250 
251  if (!logfile) {
252  return;
253  }
254 
255  (void) ctime_r(&now, nowstr);
256  nowstr[CTIME_LENGTH-2] = '\0'; /* remove trailing linefeed */
257 
258  fprintf(logfile, "[%s] %s[%i] %s: %s\n", nowstr,
259  MY_PACKAGE_TARNAME, priority, t, message);
260  fflush(logfile);
261 }
262 
263 
268 void
269 ods_log_deeebug(const char *format, ...)
270 {
271  va_list args;
272  va_start(args, format);
273  if (log_level >= LOG_DEEEBUG) {
274  ods_log_vmsg(LOG_DEBUG, "debug ", format, args);
275  }
276  va_end(args);
277 }
278 
279 
284 void
285 ods_log_debug(const char *format, ...)
286 {
287  va_list args;
288  va_start(args, format);
289  if (log_level >= LOG_DEBUG) {
290  ods_log_vmsg(LOG_DEBUG, "debug ", format, args);
291  }
292  va_end(args);
293 }
294 
295 
300 void
301 ods_log_verbose(const char *format, ...)
302 {
303  va_list args;
304  va_start(args, format);
305  if (log_level >= LOG_INFO) {
306  ods_log_vmsg(LOG_INFO, "verbose", format, args);
307  }
308  va_end(args);
309 }
310 
311 
316 void
317 ods_log_info(const char *format, ...)
318 {
319  va_list args;
320  va_start(args, format);
321  if (log_level >= LOG_NOTICE) {
322  ods_log_vmsg(LOG_NOTICE, "msg ", format, args);
323  }
324  va_end(args);
325 }
326 
327 
332 void
333 ods_log_warning(const char *format, ...)
334 {
335  va_list args;
336  va_start(args, format);
337  if (log_level >= LOG_WARNING) {
338  ods_log_vmsg(LOG_WARNING, "warning", format, args);
339  }
340  va_end(args);
341 }
342 
343 
348 void
349 ods_log_error(const char *format, ...)
350 {
351  va_list args;
352  va_start(args, format);
353  if (log_level >= LOG_ERR) {
354  ods_log_vmsg(LOG_ERR, "error ", format, args);
355  }
356  va_end(args);
357 }
358 
359 
364 void
365 ods_log_crit(const char *format, ...)
366 {
367  va_list args;
368  va_start(args, format);
369  if (log_level >= LOG_CRIT) {
370  ods_log_vmsg(LOG_CRIT, "crit ", format, args);
371  }
372  va_end(args);
373 }
374 
375 
380 void
381 ods_log_alert(const char *format, ...)
382 {
383  va_list args;
384  va_start(args, format);
385  if (log_level >= LOG_ALERT) {
386  ods_log_vmsg(LOG_ALERT, "alert ", format, args);
387  }
388  va_end(args);
389 }
390 
391 
396 void
397 ods_fatal_exit(const char *format, ...)
398 {
399  va_list args;
400  va_start(args, format);
401  if (log_level >= LOG_CRIT) {
402  ods_log_vmsg(LOG_CRIT, "fatal ", format, args);
403  }
404  va_end(args);
405  abort();
406 }