Mercurial > notdcc
diff dcclib/error_msg.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcclib/error_msg.c Tue Mar 10 13:49:58 2009 +0100 @@ -0,0 +1,361 @@ +/* Distributed Checksum Clearinghouse + * + * Copyright (c) 2008 by Rhyolite Software, LLC + * + * This agreement is not applicable to any entity which sells anti-spam + * solutions to others or provides an anti-spam solution as part of a + * security solution sold to other entities, or to a private network + * which employs the DCC or uses data provided by operation of the DCC + * but does not provide corresponding data to other users. + * + * Permission to use, copy, modify, and distribute this software without + * changes for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice appear in all + * copies and any distributed versions or copies are either unchanged + * or not called anything similar to "DCC" or "Distributed Checksum + * Clearinghouse". + * + * Parties not eligible to receive a license under this agreement can + * obtain a commercial license to use DCC by contacting Rhyolite Software + * at sales@rhyolite.com. + * + * A commercial license would be for Distributed Checksum and Reputation + * Clearinghouse software. That software includes additional features. This + * free license for Distributed ChecksumClearinghouse Software does not in any + * way grant permision to use Distributed Checksum and Reputation Clearinghouse + * software + * + * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC + * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Rhyolite Software DCC 1.3.103-1.53 $Revision$ + */ + +#include "dcc_defs.h" +#include "dcc_paths.h" +#ifndef DCC_WIN32 +#include <syslog.h> +#endif + +extern void dcc_syslog_lock(void); +extern void dcc_syslog_unlock(void); + +u_char trace_quiet; + +u_char dcc_no_syslog; + +int dcc_error_priority = LOG_ERR | LOG_MAIL; +int dcc_trace_priority = LOG_NOTICE | LOG_MAIL; + + +/* commonly used, but not thread safe */ +int dcc_ex_code = EX_UNAVAILABLE; + + +DCC_PATH dcc_progname; +int dcc_progname_len; + +#ifdef HAVE___PROGNAME +extern const char *__progname; +#endif + + +static void +clean_stdfd(int stdfd) +{ + struct stat sb; + int fd; + + if (0 > fstat(stdfd, &sb) && errno == EBADF) { + fd = open(_PATH_DEVNULL, 0, O_RDWR); + if (fd < 0) /* ignore errors we can't help */ + return; + if (fd != stdfd) { + dup2(fd, stdfd); + close(fd); + } + } +} + + + +/* prevent surprises from uses of stdio FDs by ensuring that the FDs are open */ +void +clean_stdio(void) +{ + clean_stdfd(STDIN_FILENO); + clean_stdfd(STDOUT_FILENO); + clean_stdfd(STDERR_FILENO); +} + + + +void +dcc_syslog_init(u_char use_syslog, + const char *argv0 UATTRIB, const char *suffix) +{ + const char *p; + + /* Solaris defaults to "syslog" with a null identification string, + * but does not seem to have __progname set by crt0. */ +#undef GOT_PROGNAME +#ifdef HAVE_GETPROGNAME + p = getprogname(); +# define GOT_PROGNAME +#endif +#if defined(HAVE___PROGNAME) && !defined(GOT_PROGNAME) + p = __progname; +# define GOT_PROGNAME +#endif +#ifndef GOT_PROGNAME + p = strrchr(argv0, '/'); +#ifdef DCC_WIN32 + if (!p) + p = strrchr(argv0, '\\'); +#endif + if (!p) + p = argv0; + else + ++p; +#ifdef DCC_WIN32 + /* strip ".exe" from Windows progam name */ + dcc_progname_len = strlen(p); + if (dcc_progname_len > LITZ(".exe") + && !CLITCMP(&p[dcc_progname_len-LITZ(".exe")], ".exe")) { + char *p1 = strdup(p); + p1[dcc_progname_len-LITZ(".exe")] = '\0'; + p = p1; + } +#endif /* DCC_WIN32 */ +#endif /* !GOT_PROGNAME */ + snprintf(dcc_progname, sizeof(dcc_progname), "%s%s", + p, suffix ? suffix : ""); + dcc_progname_len = strlen(dcc_progname); + + /* ensure that stdout and stderr exist so that when we open + * database or other files, we don't get file descriptor 1 or 2 + * and then later write error messages to them. */ + clean_stdio(); + +#ifdef DCC_WIN32 + dcc_no_syslog = 1; +#else + /* Don't wait for the console if somehow we must use it, + * because that messes up dccm. */ +#ifndef LOG_NOWAIT +#define LOG_NOWAIT 0 +#endif + openlog(dcc_progname, LOG_PID | LOG_NOWAIT, LOG_MAIL); + if (!use_syslog) + dcc_no_syslog = 1; +#endif /* DCC_WIN32 */ +} + + + +void +dcc_vfatal_msg(const char *p, va_list args) +{ + char logbuf[LOGBUF_SIZE]; + int i; + + /* write the message with the "fatal error" addition as + * a single message to syslog */ + i = vsnprintf(logbuf, sizeof(logbuf), p, args); + if (i >= ISZ(logbuf)) + strcpy(&logbuf[ISZ(logbuf)-sizeof("...")], "..."); + + fflush(stdout); /* keep stderr and stdout straight */ + fprintf(stderr, "%s; fatal error\n", logbuf); + fflush(stderr); + + if (dcc_no_syslog) + return; + + dcc_syslog_lock(); + syslog(dcc_error_priority, "%s; fatal error", logbuf); + closelog(); + dcc_syslog_unlock(); +} + + + +int +dcc_verror_msg(const char *p, va_list args) +{ + char logbuf[LOGBUF_SIZE]; + int i; + + i = vsnprintf(logbuf, sizeof(logbuf), p, args); + if (i >= ISZ(logbuf)) { + strcpy(&logbuf[ISZ(logbuf)-sizeof("...")], "..."); + i = ISZ(logbuf)-1; + } else if (i == 0) { + i = snprintf(logbuf, sizeof(logbuf), "(empty error message)"); + } + + fflush(stdout); /* keep stderr and stdout straight */ + fwrite(logbuf, i, 1, stderr); + if (logbuf[i-1] != '\n') { + fwrite("\n", 1, 1, stderr); + ++i; + } + + if (!dcc_no_syslog) { + dcc_syslog_lock(); + syslog(dcc_error_priority, "%s", logbuf); + dcc_syslog_unlock(); + } + + return i; +} + + + +void PATTRIB(1,2) +dcc_error_msg(const char *p, ...) +{ + va_list args; + + va_start(args, p); + dcc_verror_msg(p, args); + va_end(args); +} + + + +void +dcc_vtrace_msg(const char *p, va_list args) +{ + char logbuf[LOGBUF_SIZE]; + int i; + + /* Some systems including Linux with gcc 3.4.2 on AMD 64 processors + * do not allow two uses of a va_list but requires va_copy() + * Other systems do not have any notion of va_copy(). */ + i = vsnprintf(logbuf, sizeof(logbuf), p, args); + if (i >= ISZ(logbuf)) + strcpy(&logbuf[ISZ(logbuf)-sizeof("...")], "..."); + + fflush(stdout); /* keep stderr and stdout straight */ + fprintf(stderr, "%s\n", logbuf); + + if (!dcc_no_syslog) { + dcc_syslog_lock(); + syslog(dcc_trace_priority, "%s", logbuf); + dcc_syslog_unlock(); + } +} + + + +void PATTRIB(1,2) +dcc_trace_msg(const char *p, ...) +{ + va_list args; + + va_start(args, p); + dcc_vtrace_msg(p, args); + va_end(args); +} + + + +/* send only to system log if being quiet */ +void PATTRIB(1,2) +quiet_trace_msg(const char *p, ...) +{ + va_list args; + + va_start(args, p); + if (trace_quiet) { + vsyslog(dcc_trace_priority, p, args); + } else { + dcc_vtrace_msg(p, args); + } + va_end(args); +} + + + +void +dcc_vpemsg(int ex_code, DCC_EMSG emsg, const char *msg, va_list args) +{ + if (!emsg) { + dcc_verror_msg(msg, args); + } else { + dcc_ex_code = ex_code; + vsnprintf(emsg, sizeof(DCC_EMSG), msg, args); + } +} + + + +void PATTRIB(3,4) +dcc_pemsg(int ex_code, DCC_EMSG emsg, const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + dcc_vpemsg(ex_code, emsg, msg, args); + va_end(args); +} + + + +const char * +fnm_lno(DCC_FNM_LNO_BUF *buf, const char *fnm, int lno) +{ + DCC_PATH tmp; + + if (!fnm || *fnm == '\0') { + buf->b[0] = '\0'; + } else { + fnm2abs(tmp, fnm, ""); + snprintf(buf->b, sizeof(buf->b), DCC_FNM_LNO_PAT, lno, tmp); + } + return buf->b; +} + + + +int +dcc_vearly_log(EARLY_LOG *el, const char *p, va_list args) +{ +# define ELIPS_STR "...\n" + int max_len, len; + + max_len = sizeof(el->buf) - el->len; + if (max_len <= 0) + return 0; + + len = vsnprintf(&el->buf[el->len], max_len, p, args); + if (len < max_len) { + el->len += len; + return len; + } else { + memcpy(&el->buf[sizeof(el->buf)-LITZ(ELIPS_STR)], + ELIPS_STR, LITZ(ELIPS_STR)); + el->len = sizeof(el->buf); + return max_len; + } + +#undef ELIPS_STR +} + + + +const char * +optopt2str(int i) +{ + static char b[] = "-x"; + + b[1] = i; + return b; +}