/* ***************************************************************************** * * $RCSfile: errabort.c,v $ * $Date: 1998/07/29 13:02:50 $ * $Source: /home/richard/Xml/RCS/errabort.c,v $ * $Revision: 1.9 $ * $Author: richard $ * ***************************************************************************** * * Copyright 1998, Brown University and Richard Goerwitz * ***************************************************************************** * * Routines for printing warnings and for printing errors (and, in * the latter case, exiting). Prototypes in errabort.h. * * The errabort() and errwarn() routines have a quirky syntax and * usage. Their first argument is an error number that is used to * retrieve a string from the message catalog (named, by default, * "messages"). The thing is that these arguments also take a * redundant "format" argument, which serves as a default, in case * the message catalog isn't available. * * Example: * * if ((variable = malloc (sizeof (some_thing)) == NULL) * errabort (40, "malloc error in %s\n", "this_function()"); * * The trick is that arg 2 ("malloc error in %s\n") is normally * supplied by the message catalog (when errabort sees an error * number of "40" it knows what string to fetch). Only if the * message catalog is absent or otherwise unavailable is the default, * given above, actually used. * * BTW, be careful when providing arguments to errabort() and * errwarn() that (when they're all converted to strings) they occupy * no more than MAXPATHLEN * 4 bytes. * ***************************************************************************** */ #include "general.h" #include "errabort.h" #include "getmessage.h" #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYSLOG_H # include #else # ifndef HAVE_SYSLOG # define syslog(a,b) fprintf(stderr, "%s\n", (b)); # endif #endif #ifndef ERRBUFSIZE # define ERRBUFSIZE (MAXPATHLEN * 4) #endif #ifndef MAX_KEY_LEN # define MAX_KEY_LEN (32) #endif /* MESSAGE_KEY_LEN */ int errabort (int errnum, char *format, ...) { size_t i; #ifdef HAVE_VSNPRINTF size_t len; #endif va_list valst; char *tmp, *message_key; char *errbuf, *program_name; program_name = xmlparse_env.program_name; if (program_name == NULL) program_name = "xmlparse"; #ifdef STDC_HEADERS va_start (valst, format); #else va_start (valst); #endif /* See if there's an entry in the message catalog for errnum. If * so, use that entry as our format string. Otherwise, just use the * default (supplied) format string. */ message_key = malloc (MAX_KEY_LEN); #ifdef HAVE_VSNPRINTF if (snprintf (message_key, MAX_KEY_LEN, "%d", errnum) > 0) #else if (sprintf (message_key, "%d", errnum) > 0) #endif if ((tmp = getmessage (xmlparse_env.message_catalog, message_key)) != NULL) format = tmp; errbuf = malloc (i = (strlen (program_name) + ERRBUFSIZE)); #ifdef HAVE_VSNPRINTF while (snprintf (errbuf, i, "%s error %d: ", program_name, errnum) == i) errbuf = realloc (errbuf, i *= 2); len = strlen (errbuf); while (vsnprintf (errbuf + len, i - len, format, valst) == (i - len)) errbuf = realloc (errbuf, i *= 2); #else sprintf (errbuf, "%s error %d: ", program_name, errnum); vsprintf (errbuf + strlen (errbuf), format, valst); #endif /* Just do it as a kind of memory integrity check */ xwrap (errdebug (1, "%s", errbuf)); if (xmlparse_env.use_syslog == yes) syslog (LOG_ERR | LOG_DAEMON, "%s", errbuf); else { fprintf (stderr, "%s error %d: ", program_name, errnum); vfprintf (stderr, format, valst); } free (errbuf); exit (errnum); } /* * errwarn: * * Essentially the same as errabort, except that it does all the * printing of messages, then returns, rather than aborting. Get * it: err*warn* (vs. errabort). */ int errwarn (int warnnum, char *format, ...) { static size_t i; #ifdef HAVE_VSNPRINTF static size_t len; #endif va_list valst; static char *warnbuf = NULL; static char *message_key = NULL; static size_t errbufsize = ERRBUFSIZE; char *tmp, *program_name; program_name = xmlparse_env.program_name; if (program_name == NULL) program_name = "xmlparse"; #ifdef STDC_HEADERS va_start (valst, format); #else va_start (valst); #endif /* See if there's an entry in the message catalog for warnnum. If * so, use that entry as our format string. Otherwise, just use the * default (supplied) format string. */ if (message_key == NULL) message_key = malloc (MAX_KEY_LEN); #ifdef HAVE_VSNPRINTF if (snprintf (message_key, MAX_KEY_LEN, "%d", warnnum) != MAX_KEY_LEN) #else if (sprintf (message_key, "%d", warnnum) > 0) #endif if ((tmp = getmessage (xmlparse_env.message_catalog, message_key)) != NULL) format = tmp; if (warnbuf == NULL) warnbuf = malloc (i = (strlen (program_name) + errbufsize)); #ifdef HAVE_VSNPRINTF while (snprintf (warnbuf, i, "%s warning %d: ", program_name, warnnum) == i) warnbuf = realloc (warnbuf, i = (strlen (program_name) + (errbufsize *= 2))); len = strlen (warnbuf); while (vsnprintf (warnbuf + len, i - len, format, valst) == (i - len)) warnbuf = realloc (warnbuf, i = (strlen (program_name) + (errbufsize *= 2))); #else sprintf (warnbuf, "%s warning %d: ", program_name, warnnum); vsprintf (warnbuf + strlen (warnbuf), format, valst); #endif xwrap (errdebug (3, "%s", warnbuf)); if (xmlparse_env.use_syslog == yes) syslog (LOG_WARNING | LOG_DAEMON, "%s", warnbuf); else { fprintf (stderr, "%s warning %d: ", program_name, warnnum); vfprintf (stderr, format, valst); } va_end (valst); return warnnum; } #ifndef XML_NODEBUG /* * errdebug: * * Call syntax is like that of errabort, except that the first (int) * argument specifies a debug level. Errdebug() then compares this * level to the global xmlparse_env.debug_level (set in main()). If the * global xmlparse_env.debug_level is greater than or equal to the level * specified in arg 1, then then the debugging message (args 2 and * following) gets displayed. * * Unlike errabort, errdebug ALWAYS USES syslog(3) (LOG_DEBUG | * LOG_DAEMON). * * Returns -1 if the global xmlparse_env.debug_level is lower than the * debug level given as arg 1. Otherwise, returns arg 1. */ int errdebug (int level, char *format, ...) { static size_t i; #ifdef HAVE_VSNPRINTF static size_t len; static size_t errbufsize = ERRBUFSIZE; #endif va_list valst; char *program_name; static char *debugbuf = NULL; program_name = xmlparse_env.program_name; if (program_name == NULL) program_name = "xmlparse"; /* set in main() */ if (xmlparse_env.debug_level < level) return 0; #ifdef STDC_HEADERS va_start (valst, format); #else va_start (valst); #endif if (debugbuf == NULL) debugbuf = malloc (i = (strlen (program_name) + ERRBUFSIZE)); #ifdef HAVE_VSNPRINTF while (snprintf (debugbuf, i, "%s debug msg, level %d (pid %d): ", program_name, level, getpid()) == i) debugbuf = realloc (debugbuf, i = (strlen (program_name) + (errbufsize *= 2))); len = strlen (debugbuf); while (vsnprintf (debugbuf + len, i - len, format, valst) == (i - len)) debugbuf = realloc (debugbuf, i = (strlen (program_name) + (errbufsize *= 2))); #else sprintf (debugbuf, "%s debug msg, level %d (pid %d): ", program_name, level, getpid()); vsprintf (debugbuf + strlen (debugbuf), format, valst); #endif syslog (LOG_DEBUG | LOG_DAEMON, "%s\n", debugbuf); va_end (valst); return level; } #endif /* XML_NODEBUG */