1 /**************************************************************************************************
2 	$Id: error.c,v 1.42 2005/04/20 16:49:11 bboy Exp $
3 
4 	error.c: Error reporting and message output functions.
5 
6 	Copyright (C) 2002-2005  Don Moore <bboy@bboy.net>
7 
8 	This program 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 2 of the License, or
11 	(at Your option) any later version.
12 
13 	This program 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 this program; if not, write to the Free Software
20 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 **************************************************************************************************/
22 
23 #include "mydnsutil.h"
24 
25 #define ERROR_MAXMSGLEN	1024
26 
27 /* The name of the currently running program */
28 char	*progname = (char *)PACKAGE;
29 
30 /* Should ERR_VERBOSE cause output? */
31 int	err_verbose = 0;
32 
33 #if DEBUG_ENABLED
34 /* Should ERR_DEBUG cause output? */
35 int	err_debug = 0;
36 #endif
37 
38 /* Should error functions output to a file? */
39 FILE	*err_file = NULL;
40 
41 /* The last error message output, so we don't repeat ourselves */
42 static char err_last[ERROR_MAXMSGLEN + 1] = "";
43 
44 
45 /**************************************************************************************************
46 	ERROR_INIT
47 	Initialize error reporting and output functions.
48 **************************************************************************************************/
49 void
error_init(argv0,facility)50 error_init(argv0, facility)
51 	const char *argv0;	/* argv[0] from calling program */
52 	int facility;			/* Logging facility (i.e. LOG_DAEMON, etc) */
53 {
54 	int option;
55 
56 	/* Save program name */
57 	if (argv0)
58 	{
59 		char *c;
60 		if ((c = strrchr(argv0, '/')))
61 			progname = strdup(c+1);
62 		else
63 			progname = strdup((char *)argv0);
64 		if (!progname)
65 			Err("strdup");
66 	}
67 
68 	/* Open syslog */
69 	if (!err_file)
70 	{
71 		option = LOG_CONS | LOG_NDELAY | LOG_PID;
72 #ifdef LOG_PERROR
73 		if (isatty(STDERR_FILENO))
74 			option |= LOG_PERROR;
75 #endif
76 		openlog(progname, option, facility);
77 	}
78 }
79 /*--- error_init() ------------------------------------------------------------------------------*/
80 
81 
82 /**************************************************************************************************
83 	_ERROR_OUT
84 	This function handles all program output after command line handling.
85 	Always returns -1.
86 **************************************************************************************************/
87 static void
_error_out(int priority,int errappend,int isfatal,const char * msg)88 _error_out(
89 	int priority,				/* Priority (i.e. LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG) */
90 	int errappend,				/* Append strerror(errno)? */
91 	int isfatal,				/* Is this error fatal? */
92 	const char *msg
93 )
94 {
95 	static char out[ERROR_MAXMSGLEN + 2];
96 	static int  repeat = 0;
97 	int len;
98 
99 	/* Construct 'out' - the output */
100 #if SHOW_PID_IN_ERRORS
101 	if (err_file && errappend)
102 		len = snprintf(out, sizeof(out) - 2, "%s [%d]: %s: %s", progname, getpid(), msg, strerror(errno));
103 	else if (err_file)
104 		len = snprintf(out, sizeof(out) - 2, "%s [%d]: %s", progname, getpid(), msg);
105 #else
106 	if (err_file && errappend)
107 		len = snprintf(out, sizeof(out) - 2, "%s: %s: %s", progname, msg, strerror(errno));
108 	else if (err_file)
109 		len = snprintf(out, sizeof(out) - 2, "%s: %s", progname, msg);
110 #endif
111 	else if (errappend)
112 		len = snprintf(out, sizeof(out) - 2, "%s: %s", msg, strerror(errno));
113 	else
114 		len = snprintf(out, sizeof(out) - 2, "%s", msg);
115 
116 	/* Don't output the same error message again and again */
117 	if (strcmp(out, err_last))
118 	{
119 		if (repeat)
120 		{
121 			if (err_file)
122 				fprintf(err_file, _("%s: last message repeated %d times\n"), progname, repeat + 1);
123 			else
124 				syslog(priority, _("last message repeated %d times"), repeat + 1);
125 		}
126 		repeat = 0;
127 		strncpy(err_last, out, ERROR_MAXMSGLEN);
128 		if (err_file)
129 		{
130 			out[len++] = '\n';
131 			out[len] = '\0';
132 			fwrite(out, len, 1, err_file);
133 			fflush(err_file);
134 		}
135 		else
136 			syslog(priority, "%s", out);
137 	}
138 	else
139 		repeat++;
140 
141 	/* Abort if the error should be fatal */
142 	if (isfatal)
143 		exit(EXIT_FAILURE);
144 }
145 /*--- _error_out() ------------------------------------------------------------------------------*/
146 
147 
148 /**************************************************************************************************
149    _ERROR_ASSERT_FAIL
150    This is called by the macro "Assert" if an assertion fails.
151 **************************************************************************************************/
152 void
_error_assert_fail(const char * assertion)153 _error_assert_fail(const char *assertion)
154 {
155 	char msg[BUFSIZ];
156 
157 	snprintf(msg, sizeof(msg), "assertion failed: %s", assertion);
158 
159    _error_out(LOG_ERR, 0, 1, msg);
160 }
161 /*--- _error_assert_fail() ----------------------------------------------------------------------*/
162 
163 
164 #if DEBUG_ENABLED
165 /**************************************************************************************************
166 	DEBUG
167 **************************************************************************************************/
168 void
Debug(const char * fmt,...)169 Debug(const char *fmt, ...)
170 {
171 	char msg[BUFSIZ];
172 	va_list ap;
173 
174 	if (!err_debug)
175 		return;
176 
177 	/* Construct output string */
178 	va_start(ap, fmt);
179 	vsnprintf(msg, sizeof(msg), fmt, ap);
180 	va_end(ap);
181 
182 	_error_out(LOG_DEBUG, 0, 0, msg);
183 }
184 /*--- Debug() -----------------------------------------------------------------------------------*/
185 #endif
186 
187 
188 /**************************************************************************************************
189 	VERBOSE
190 **************************************************************************************************/
191 void
Verbose(const char * fmt,...)192 Verbose(const char *fmt, ...)
193 {
194 	char msg[BUFSIZ];
195 	va_list ap;
196 
197 	if (!err_verbose)
198 		return;
199 
200 	/* Construct output string */
201 	va_start(ap, fmt);
202 	vsnprintf(msg, sizeof(msg), fmt, ap);
203 	va_end(ap);
204 
205 	_error_out(LOG_WARNING, 0, 0, msg);
206 }
207 /*--- Verbose() ---------------------------------------------------------------------------------*/
208 
209 
210 /**************************************************************************************************
211 	NOTICE
212 **************************************************************************************************/
213 void
Notice(const char * fmt,...)214 Notice(const char *fmt, ...)
215 {
216 	char msg[BUFSIZ];
217 	va_list ap;
218 
219 	/* Construct output string */
220 	va_start(ap, fmt);
221 	vsnprintf(msg, sizeof(msg), fmt, ap);
222 	va_end(ap);
223 
224 	_error_out(LOG_WARNING, 0, 0, msg);
225 }
226 /*--- Notice() ----------------------------------------------------------------------------------*/
227 
228 
229 /**************************************************************************************************
230 	WARN
231 **************************************************************************************************/
232 int
Warn(const char * fmt,...)233 Warn(const char *fmt, ...)
234 {
235 	char msg[BUFSIZ];
236 	va_list ap;
237 
238 	/* Construct output string */
239 	va_start(ap, fmt);
240 	vsnprintf(msg, sizeof(msg), fmt, ap);
241 	va_end(ap);
242 
243 	_error_out(LOG_WARNING, 1, 0, msg);
244 	return (-1);
245 }
246 /*--- Warn() ------------------------------------------------------------------------------------*/
247 
248 
249 /**************************************************************************************************
250 	WARNX
251 **************************************************************************************************/
252 int
Warnx(const char * fmt,...)253 Warnx(const char *fmt, ...)
254 {
255 	char msg[BUFSIZ];
256 	va_list ap;
257 
258 	/* Construct output string */
259 	va_start(ap, fmt);
260 	vsnprintf(msg, sizeof(msg), fmt, ap);
261 	va_end(ap);
262 
263 	_error_out(LOG_WARNING, 0, 0, msg);
264 	return (-1);
265 }
266 /*--- Warnx() -----------------------------------------------------------------------------------*/
267 
268 
269 /**************************************************************************************************
270 	ERR
271 **************************************************************************************************/
272 void
Err(const char * fmt,...)273 Err(const char *fmt, ...)
274 {
275 	char msg[BUFSIZ];
276 	va_list ap;
277 
278 	/* Construct output string */
279 	va_start(ap, fmt);
280 	vsnprintf(msg, sizeof(msg), fmt, ap);
281 	va_end(ap);
282 
283 	_error_out(LOG_ERR, 1, 1, msg);
284 }
285 /*--- Err() -------------------------------------------------------------------------------------*/
286 
287 
288 /**************************************************************************************************
289 	ERRX
290 **************************************************************************************************/
291 void
Errx(const char * fmt,...)292 Errx(const char *fmt, ...)
293 {
294 	char msg[BUFSIZ];
295 	va_list ap;
296 
297 	/* Construct output string */
298 	va_start(ap, fmt);
299 	vsnprintf(msg, sizeof(msg), fmt, ap);
300 	va_end(ap);
301 
302 	_error_out(LOG_ERR, 0, 1, msg);
303 }
304 /*--- Errx() ------------------------------------------------------------------------------------*/
305 
306 
307 /**************************************************************************************************
308 	WARNSQL
309 	Outputs a warning caused by an SQL query failure.
310 **************************************************************************************************/
311 int
WarnSQL(PGconn * pgsql,const char * fmt,...)312 WarnSQL(
313 #if USE_PGSQL
314 	PGconn *pgsql,
315 #else
316 	MYSQL *mysql,
317 #endif
318 	const char *fmt, ...)
319 {
320 	char msg[BUFSIZ], out[BUFSIZ * 2];
321 	va_list ap;
322 
323 	/* Construct output string */
324 	va_start(ap, fmt);
325 	vsnprintf(msg, sizeof(msg), fmt, ap);
326 	va_end(ap);
327 
328 #if USE_PGSQL
329 	{
330 		char *errmsg = PQerrorMessage(pgsql), *c;
331 
332 		for (c = errmsg; *c; c++)
333 			if (*c == '\r' || *c == '\n')
334 				*c = ' ';
335 		strtrim(errmsg);
336 
337 		snprintf(out, sizeof(out), "%s: %s (errno=%d)", msg, errmsg, errno);
338 	}
339 #else
340 	snprintf(out, sizeof(out), "%s: %s (errno=%d)", msg, mysql_error(mysql), errno);
341 #endif
342 	_error_out(LOG_WARNING, 0, 0, out);
343 
344 	return (-1);
345 }
346 /*--- WarnSQL() ---------------------------------------------------------------------------------*/
347 
348 
349 /**************************************************************************************************
350 	SQL_ERRMSG
351 **************************************************************************************************/
352 char *
sql_errmsg(PGconn * pgsql)353 sql_errmsg(
354 #if USE_PGSQL
355 	PGconn *pgsql
356 #else
357 	MYSQL *mysql
358 #endif
359 )
360 {
361 	static char msg[BUFSIZ];
362 
363 #if USE_PGSQL
364 	{
365 		char *errmsg = PQerrorMessage(pgsql), *c;
366 
367 		for (c = errmsg; *c; c++)
368 			if (*c == '\r' || *c == '\n')
369 				*c = ' ';
370 		strtrim(errmsg);
371 
372 		snprintf(msg, sizeof(msg), "%s (errno=%d)", errmsg, errno);
373 	}
374 #else
375 	snprintf(msg, sizeof(msg), "%s (errno=%d)", mysql_error(mysql), errno);
376 #endif
377 	return (msg);
378 }
379 /*--- sql_errmsg() ------------------------------------------------------------------------------*/
380 
381 
382 /**************************************************************************************************
383 	ERRSQL
384 **************************************************************************************************/
385 void
ErrSQL(PGconn * pgsql,const char * fmt,...)386 ErrSQL(
387 #if USE_PGSQL
388 	PGconn *pgsql,
389 #else
390 	MYSQL *mysql,
391 #endif
392 	const char *fmt, ...)
393 {
394 	char msg[BUFSIZ], out[BUFSIZ * 2];
395 	va_list ap;
396 
397 	/* Construct output string */
398 	va_start(ap, fmt);
399 	vsnprintf(msg, sizeof(msg), fmt, ap);
400 	va_end(ap);
401 
402 #if USE_PGSQL
403 	{
404 		char *errmsg = PQerrorMessage(pgsql), *c;
405 
406 		for (c = errmsg; *c; c++)
407 			if (*c == '\r' || *c == '\n')
408 				*c = ' ';
409 		strtrim(errmsg);
410 
411 		snprintf(out, sizeof(out), "%s: %s (errno=%d)", msg, errmsg, errno);
412 	}
413 #else
414 	snprintf(out, sizeof(out), "%s: %s (errno=%d)", msg, mysql_error(mysql), errno);
415 #endif
416 
417 	_error_out(LOG_ERR, 0, 1, out);
418 }
419 /*--- ErrSQL() ----------------------------------------------------------------------------------*/
420 
421 /* vi:set ts=3: */
422