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