/* Distributed Checksum Clearinghouse * * Copyright (c) 2006 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 for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * Parties not eligible to receive a license under this agreement can * obtain a commercial license to use DCC and permission to use * U.S. Patent 6,330,590 by contacting Commtouch at http://www.commtouch.com/ * or by email to nospam@commtouch.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.50-1.43 $Revision$ */ #include "dcc_defs.h" #include "dcc_paths.h" #ifndef DCC_WIN32 #include #endif extern void dcc_syslog_lock(void); extern void dcc_syslog_unlock(void); 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) { #ifndef DCC_WIN32 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); } } #endif } /* 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, '/'); if (!p) p = argv0; else ++p; #endif snprintf(dcc_progname, sizeof(dcc_progname), "%s%s", p, suffix ? suffix : ""); dcc_progname_len = strlen(dcc_progname); #ifdef DCC_WIN32 dcc_no_syslog = 1; #else /* 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(); /* 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); dcc_no_syslog = !use_syslog; #endif /* DCC_WIN32 */ } void dcc_vfatal_msg(const char *p, va_list args) { char sbuf[200]; int i; DCC_ARGS2_COPY(); fflush(stdout); /* keep stderr and stdout straight */ vfprintf(stderr, p, DCC_ARGS2); fputs("; fatal error\n", stderr); fflush(stderr); DCC_ARGS2_END(); if (dcc_no_syslog) return; dcc_syslog_lock(); /* try to write the message with the "fatal error" addition as * a single message */ i = vsnprintf(sbuf, sizeof(sbuf), p, args); if (i < ISZ(sbuf)-ISZ("fatal error")) { syslog(dcc_error_priority, "%s; fatal error", sbuf); } else { vsyslog(dcc_error_priority, p, args); syslog(dcc_error_priority, "fatal error"); } closelog(); dcc_syslog_unlock(); } int dcc_verror_msg(const char *p, va_list args) { int i; DCC_ARGS2_COPY(); fflush(stdout); /* keep stderr and stdout straight */ i = vfprintf(stderr, p, DCC_ARGS2); fputc('\n', stderr); DCC_ARGS2_END(); if (dcc_no_syslog) return i+1; dcc_syslog_lock(); vsyslog(dcc_error_priority, p, args); dcc_syslog_unlock(); return i+1; } 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) { DCC_ARGS2_COPY(); fflush(stdout); /* keep stderr and stdout straight */ vfprintf(stderr, p, DCC_ARGS2); fputc('\n', stderr); DCC_ARGS2_END(); if (dcc_no_syslog) return; dcc_syslog_lock(); vsyslog(dcc_trace_priority, p, args); 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); } 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) { if (!fnm || *fnm == '\0') buf[0] = '\0'; else snprintf(buf, sizeof(DCC_FNM_LNO_BUF), DCC_FNM_LNO_PAT, lno, fnm); return buf; } 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)-STRZ(ELIPS_STR)], ELIPS_STR, STRZ(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; }