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