1 /* error.c - Error handling
2 
3    Copyright (C) 2000, 2001 Thomas Moestl
4    Copyright (C) 2003, 2004, 2005, 2011 Paul A. Rombouts
5 
6   This file is part of the pdnsd package.
7 
8   pdnsd is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12 
13   pdnsd is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   along with pdnsd; see the file COPYING. If not, see
20   <http://www.gnu.org/licenses/>.
21 */
22 
23 #include <config.h>
24 #include <sys/types.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <syslog.h>
28 #include <pthread.h>
29 #include <signal.h>
30 #include <string.h>
31 #include "error.h"
32 #include "helpers.h"
33 #include "conff.h"
34 
35 
36 pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;
37 volatile short int use_log_lock=0;
38 
39 /*
40  * Initialize a mutex for io-locking in order not to produce gibberish on
41  * multiple simultaneous errors.
42  */
43 /* This is now defined as an inline function in error.h */
44 #if 0
45 void init_log_lock(void)
46 {
47 	use_log_lock=1;
48 }
49 #endif
50 
51 /* We crashed? Ooops... */
crash_msg(char * msg)52 void crash_msg(char *msg)
53 {
54 	log_error("%s", msg);
55 	log_error("pdnsd probably crashed due to a bug. Please consider sending a bug");
56 	log_error("report to p.a.rombouts@home.nl or tmoestl@gmx.net");
57 }
58 
59 /* Log a warning, error or info message.
60  * If we are a daemon, use the syslog. s is a format string like in printf,
61  * the optional following arguments are the arguments like in printf */
log_message(int prior,const char * s,...)62 void log_message(int prior, const char *s, ...)
63 {
64 	int gotlock=0;
65 	va_list va;
66 	FILE *f;
67 
68 	if (use_log_lock) {
69 		gotlock=softlock_mutex(&loglock);
70 		/* If we failed to get the lock and the type of the
71 		   message is "info" or less important, then don't bother. */
72 		if(!gotlock && prior>=LOG_INFO)
73 			return;
74 	}
75 	if (global.daemon) {
76 		openlog("pdnsd",LOG_PID,LOG_DAEMON);
77 		va_start(va,s);
78 		vsyslog(prior,s,va);
79 		va_end(va);
80 		closelog();
81 	}
82 	else {
83 		f=stderr;
84 #if DEBUG > 0
85 		goto printtofile;
86 	}
87 	if(debug_p) {
88 		f=dbg_file;
89 	printtofile:
90 #endif
91 		{
92 			char ts[sizeof "* 12/31 23:59:59| "];
93 			time_t tt = time(NULL);
94 			struct tm tm;
95 
96 			if(!localtime_r(&tt, &tm) || strftime(ts, sizeof(ts), "* %m/%d %T| ", &tm) <=0)
97 				ts[0]=0;
98 			fprintf(f,"%spdnsd: %s: ", ts,
99 				prior<=LOG_CRIT?"critical":
100 				prior==LOG_ERR?"error":
101 				prior==LOG_WARNING?"warning":
102 				"info");
103 		}
104 		va_start(va,s);
105 		vfprintf(f,s,va);
106 		va_end(va);
107 		{
108 			const char *p=strchr(s,0);
109 			if(!p || p==s || *(p-1)!='\n')
110 				fputc('\n',f);
111 		}
112 	}
113 	if (gotlock)
114 		pthread_mutex_unlock(&loglock);
115 }
116 
117 
118 #if DEBUG > 0
119 /* XXX: The timestamp generation makes this a little heavy-weight */
debug_msg(int c,const char * fmt,...)120 void debug_msg(int c, const char *fmt, ...)
121 {
122 	va_list va;
123 
124 	if (!c) {
125 		char ts[sizeof "12/31 23:59:59"];
126 		time_t tt = time(NULL);
127 		struct tm tm;
128 		unsigned *id;
129 
130 		if(localtime_r(&tt, &tm) && strftime(ts, sizeof(ts), "%m/%d %T", &tm) > 0) {
131 			if((id = (unsigned *)pthread_getspecific(thrid_key)))
132 				fprintf(dbg_file,"%u %s| ", *id, ts);
133 			else
134 				fprintf(dbg_file,"- %s| ", ts);
135 		}
136 	}
137 	va_start(va,fmt);
138 	vfprintf(dbg_file,fmt,va);
139 	va_end(va);
140 	fflush(dbg_file);
141 }
142 #endif /* DEBUG */
143