/* * Copyright (c) 1993, 1994, 1995, 1996, 1998 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #ifdef _WIN32 #include #else #include #endif #include "portability.h" #include "log.h" static int log_to_systemlog; static int log_debug_messages; static void rpcapd_vlog_stderr(log_priority, PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0); static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap) { const char *tag; /* * Squelch warnings from compilers that *don't* assume that * priority always has a valid enum value and therefore don't * assume that we'll always go through one of the case arms. * * If we have a default case, compilers that *do* assume that * will then complain about the default case code being * unreachable. * * Damned if you do, damned if you don't. */ tag = ""; switch (priority) { case LOGPRIO_DEBUG: tag = "DEBUG: "; break; case LOGPRIO_INFO: tag = ""; break; case LOGPRIO_WARNING: tag = "warning: "; break; case LOGPRIO_ERROR: tag = "error: "; break; } fprintf(stderr, "rpcapd: %s", tag); vfprintf(stderr, message, ap); putc('\n', stderr); } static void rpcapd_vlog_systemlog(log_priority, PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0); #ifdef _WIN32 #define MESSAGE_SUBKEY \ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd" static void rpcapd_vlog_systemlog(log_priority priority, const char *message, va_list ap) { #if 0 static int initialized = 0; HKEY hey_handle; static HANDLE log_handle; WORD eventlog_type; DWORD event_id; char msgbuf[1024]; char *strings[1]; if (!initialized) { /* * Register our message stuff in the Registry. * * First, create the registry key for us. If the key * already exists, this succeeds and returns a handle * for it. */ if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY, &key_handle) != ERROR_SUCCESS) { /* * Failed - give up and just log this message, * and all subsequent messages, to the * standard error. */ log_to_systemlog = 0; initialized = 1; rpcapd_vlog_stderr(priority, message, ap); return; } log_handle = RegisterEventSource(NULL, "rpcapd"); initialized = 1; } switch (priority) { case LOGPRIO_DEBUG: // // XXX - what *should* we do about debug messages? // eventlog_type = EVENTLOG_INFORMATION_TYPE; event_id = RPCAPD_INFO_ID; break; case LOGPRIO_INFO: eventlog_type = EVENTLOG_INFORMATION_TYPE; event_id = RPCAPD_INFO_ID; break; case LOGPRIO_WARNING: eventlog_type = EVENTLOG_WARNING_TYPE; event_id = RPCAPD_WARNING_ID; break; case LOGPRIO_ERROR: eventlog_type = EVENTLOG_ERROR_TYPE; event_id = RPCAPD_ERROR_ID; break; default: /* Don't do this. */ return; } vsprintf(msgbuf, message, ap); strings[0] = msgbuf; /* * If this fails, how are we going to report it? */ (void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0, strings, NULL); #else rpcapd_vlog_stderr(priority, message, ap); #endif } #else static void rpcapd_vlog_systemlog(log_priority priority, const char *message, va_list ap) { static int initialized = 0; int syslog_priority; if (!initialized) { // // Open the log. // openlog("rpcapd", LOG_PID, LOG_DAEMON); initialized = 1; } switch (priority) { case LOGPRIO_DEBUG: syslog_priority = LOG_DEBUG; break; case LOGPRIO_INFO: syslog_priority = LOG_INFO; break; case LOGPRIO_WARNING: syslog_priority = LOG_WARNING; break; case LOGPRIO_ERROR: syslog_priority = LOG_ERR; break; default: /* Don't do this. */ return; } #ifdef HAVE_VSYSLOG vsyslog(syslog_priority, message, ap); #else /* * Thanks, IBM, for not providing vsyslog() in AIX! * * They also warn that the syslog functions shouldn't * be used in multithreaded programs, but the only thing * obvious that seems to make the syslog_r functions * better is that they have an additional argument * that points to the information that's static to * the syslog code in non-thread-safe versions. Most * of that data is set by openlog(); since we already * do an openlog before doing logging, and don't * change that data afterwards, I suspect that, in * practice, the regular syslog routines are OK for * us (especially given that we'd end up having one * static struct syslog_data anyway, which means we'd * just be like the non-thread-safe version). */ char logbuf[1024+1]; pcap_vsnprintf(logbuf, sizeof logbuf, message, ap); syslog(syslog_priority, "%s", logbuf); #endif } #endif void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg) { log_debug_messages = log_debug_messages_arg; log_to_systemlog = log_to_systemlog_arg; } void rpcapd_log(log_priority priority, const char *message, ...) { va_list ap; if (priority != LOGPRIO_DEBUG || log_debug_messages) { va_start(ap, message); if (log_to_systemlog) { rpcapd_vlog_systemlog(priority, message, ap); } else { rpcapd_vlog_stderr(priority, message, ap); } va_end(ap); } }