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